IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Composants Java Discussion :

[JTable] Associer un HashMap à un TableModel


Sujet :

Composants Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 63
    Par défaut [JTable] Associer un HashMap à un TableModel
    Bonjour,

    Après un après-midi entier à chercher sur Google, dans la doc de Sun, la FAQ de developpez.com, ... je me résigne à ouvrir un post ici.


    Contexte :
    Je dispose d'un HashMap contenant des produits. En index, j'ai l'ID du produit, et en valeur l'objet représentant un produit.

    J'ai un JTable et j'aimerais qu'il affiche mes objets produit avec deux colonnes : le libellé, et le prix. Pour l'instant j'arrive sans trop de difficultés à le remplir ligne par ligne avec le modèle de ma table (qui extends DefaultTableModel) à l'aide du code suivant.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Vector row = new Vector();
    row.add(produit.libelle);
    row.add(produit.prixUnitaire + "€");
    this.addRow(row);
    Mon problème :
    Il peut arriver que je sois amené à supprimer un produit de mon JTable. Pour supprimer un produit, j'ai seulement accès à son ID. Dans la mesure où je n'ai pas cet ID dans mon JTable (j'ai seulement accès aux coordonnées de la case sélectionnée, et rappelez-vous je n'ai que deux colonnes : le libellé et le prix), comment supprimer une ligne produit dont je précise l'ID ?

    Ce que j'aimerais :
    L'idéal serait d'associer une colonne par attribut de ma classe Produit. Mais pas tous les attributs. Par exemple, je ne veux pas afficher l'ID du produit, ou sa description complète.
    Ce qui pourrait être encore mieux, c'est que, dès que mon HashTable contenant mes produits change, ce soit automatiquement répercuté sur le JTable.
    J'ai cru comprendre (sur http://java.sun.com/docs/books/tutor...able.html#data) qu'il est possible de faire ça avec le concept MVC en créant une classe qui implémente l'interface TableModel, ou qui hérite l'une de ses sous-classes, mais je ne comprends pas comment faire.


    Merci d'avance pour votre aide !

  2. #2
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Bah il faut tout simplement que tu fournisses ton propre modèle. Ce modéle contenant comme donnée une Lis<Produit>.
    Puis il te suffit d'adapter les getColumnCount, getColumnName, getValueAt et autres méthode usuelles de la façon qui t'arrange.
    De ce fait tu pourras parfaitement avoir une méthode removeRow(String rowId) puisque tu auras ton objet dans le modèle, et de ce fait son ID.

    PS: penser à employer les méthodes fireXXX héritée de la classe AbstractTableModel

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 63
    Par défaut
    Merci de t'intéresser à mon problème Sinok !

    J'arrive effectivement à afficher ce que je veux avec la méthode getValueAt(int row, int col).

    Ce que je n'arrive pas à comprendre, c'est comment faire le lien entre les coordonnées de la case que j'ai sélectionnée, et l'ID de mon produit.

    Je vais donner un autre exemple :
    Si au lieu d'avoir deux colonne, j'en rajoute une pour la quantité. Lorsque je veux ajouter un produit qui existe déjà dans mon JTable, je n'ajoute pas une ligne à mon JTable, mais j'incrémente la case "quantité" dont la ligne correspond au produit que je désire ajouter.
    Comment accéder à l'ID de mon produit, sachant que ne sais pas à quelle ligne mon produit a précédemment été ajouté ?
    Faut-il que, à chaque ajout de produit, je doive mémoriser le numéro de ligne à laquelle il à été ajouté ? Faut-il que j'ajoute un attribut "ligne" à ma classe Produit ?

    Merci encore !

  4. #4
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Essentiellement c'est au niveau conception que ton problème se situe.

    Dans ton cas il vaudrait mieux avoir un objet qui contient sa propre ID en tant qu'attribut.

    Puis créer un TableModel s'appuyant sur une liste de ces objets.
    Ensuite tu crées une méthode removeRowAt(int row). Dans cette méthode tu récupères l'objet situé à l'index Row dans ta liste tu effectues les opérations voulues, puis tu supprimes cet objet de ta liste

    Soit la classe Produit suivante qui contient son propre identifiant accessible via el mécanisme de getters/setters standards (attention à ne pas rendre les attributs publics comme tu le fais, cela casse le principe d'encapsulation afférent à la POO)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    package dvp;
     
    public class Produit {
     
        private String id;
        private String libelle;
        private Integer prixUnitaire;
        /**
         * @return the id
         */
        public String getId() {
            return id;
        }
        /**
         * @param id the id to set
         */
        public void setId(String id) {
            this.id = id;
        }
        /**
         * @return the libelle
         */
        public String getLibelle() {
            return libelle;
        }
        /**
         * @param libelle the libelle to set
         */
        public void setLibelle(String libelle) {
            this.libelle = libelle;
        }
        /**
         * @return the prixUnitaire
         */
        public Integer getPrixUnitaire() {
            return prixUnitaire;
        }
        /**
         * @param prixUnitaire the prixUnitaire to set
         */
        public void setPrixUnitaire(Integer prixUnitaire) {
            this.prixUnitaire = prixUnitaire;
        }
     
     
    }
    Celà nous donne un TableModel dans ce style:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
     
    package dvp;
     
    import java.util.List;
     
    import javax.swing.table.AbstractTableModel;
     
    public class ProduitTableModel extends AbstractTableModel{
     
     
        private List<Produit> datas;
     
        @Override
        public int getColumnCount() {
            // TODO Auto-generated method stub
            return 2;
        }
     
        @Override
        public int getRowCount() {
            // TODO Auto-generated method stub
            return datas != null ? datas.size():0;
        }
     
        @Override
        public Object getValueAt(int row, int col) {
            Produit p = datas.get(row);
            switch (col) {
            case 0:            
                return p.getLibelle();
            case 1:
                return p.getPrixUnitaire();        
            }
            return null;
        }
     
        /* (non-Javadoc)
         * @see javax.swing.table.AbstractTableModel#getColumnClass(int)
         */
        @Override
        public Class<?> getColumnClass(int col) {
            switch (col) {
            case 0:            
                return String.class;
            case 1:
                return Integer.class;        
            }
            return Object.class;
        }
     
        /* (non-Javadoc)
         * @see javax.swing.table.AbstractTableModel#getColumnName(int)
         */
        @Override
        public String getColumnName(int col) {
            switch (col) {
            case 0:            
                return "Libellé";
            case 1:
                return "Prix Unitaire";        
            }
            return null;
        }
     
        /* (non-Javadoc)
         * @see javax.swing.table.AbstractTableModel#setValueAt(java.lang.Object, int, int)
         */
        @Override
        public void setValueAt(Object value, int row, int col) {
            // TODO Auto-generated method stub
            Produit p = datas.get(row);
            switch (col) {
            case 0:            
                String lib = (String) value;
                p.setLibelle(lib);
                break;
            case 1:
                Integer prix = (Integer) value;
                p.setPrixUnitaire(prix);
                break;        
            }
            //On notifie la JTable qu'une valeur a été modifiée
            fireTableCellUpdated(row, col);
        }
     
        public void removeRow(int row) {
            Produit p = datas.get(row);
            //Faire quelquechose avec p sachant que p contient sa propre id que l'on obtient via la méthode getId()
            datas.remove(p);
            //On notifie la JTable qu'une ligne a été supprimée
            fireTableRowsDeleted(row, row);
        }
    }

    De plus quand on manipule une JTable, toute action programmatique sur les données doit être fait via le modèle de la JTable, pas via la JTable elle même.

    De fait, si tu veux supprimer une ligne de façon programmatique, il te suffit de récupérer le modèle de ta JTable (méthode getModel()) de la caster en ProduitTableModel et d'appeler la méthode removeRow(String id) qui recherche l'objet voulu et le supprime de la JTable.

    Des questions?

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 63
    Par défaut
    Merci Sinok, ta solution fonctionne !

    En fait, ma classe produit contenait déjà un attribut "identifiant". mais je voulais utiliser un HashMap pour retrouver les produits plus rapidement, plutôt que d'utiliser une List comme tu me l'as suggéré. En effet, l'utilisation d'une List m'oblige à parcourir mes produits avec un Iterator, ce qui est plus long que d'utiliser un HashMap (enfin, je crois...).

    Je garde ta solution puisqu'elle fonctionne, mais si tu as encore le courage de me proposer quelque chose pour le HashMap, je t'écoute

    Merci encore !

  6. #6
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    Bah le truc c'est que ton TableModel doit parcourir de toute façon en entier ta liste.

    Sinon un truc fin serait de redéfinir les méthode hashcode et equals de ton objet produit afin que deux objets ayant un même identifiant soient considérés comme égaux (la méthode equals renvoyant true) et que les valeurs renvoyées par la méthode hashcode soient les même.

    De fait tu pourras directement faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    datas.remove(monProduit);
    Avec monProduit étant une instance de produit contenant uniquement l'id de ce produit (pas besoin de plus).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Hashmap et tablemodel
    Par crofteur dans le forum Composants
    Réponses: 1
    Dernier message: 10/02/2009, 14h53
  2. jTable et TableModel
    Par nutix2003 dans le forum NetBeans
    Réponses: 4
    Dernier message: 12/10/2006, 14h39
  3. Réponses: 9
    Dernier message: 12/06/2006, 09h59
  4. Association de Jcheckbox et les lignes d'un JTable
    Par @yoyo dans le forum Composants
    Réponses: 2
    Dernier message: 23/03/2006, 10h29
  5. Probleme d'affichage d'une JTable utilisant un tablemodel
    Par garfieldcut dans le forum Composants
    Réponses: 2
    Dernier message: 13/01/2006, 11h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo