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 et JComboBox : problème lors de l'édition


Sujet :

Composants Java

  1. #1
    Membre confirmé Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Points : 554
    Points
    554
    Par défaut JTable et JComboBox : problème lors de l'édition
    Bonjour tout le monde

    J'ai une JComboBox dans une JTable,en suivant les indications contenues dans le tutorial de sun : http://java.sun.com/docs/books/tutor...nts/table.html


    J'obtiens donc comme il faut une JComboBox qui s'affiche dans les colonnes adéquates, mais lorsque je clique dessus pour affecter une nouvelle valeur a une de ces colonnes, la valeur sélectionnée devient la dernière valeur donnée à une JComboBox de la colonne.

    Cela ne m'empêche pas de changer cette valeur ensuite mais cela est genant de se retrouver lors de l'édition avec une valeur n'ayant rien à voir avec celle sélectionnée pour cette ligne précisément...

    Pour éclaircir, voici des captures d'écran :

    Je crées 2 lignes pour lesquelles j'affecte les bonnes valeurs => l'affichage est ok :




    Puis, je veux modifier le type de la ligne1, je clique donc dessus :



    Et là, il me sélectionne "Choice" alors que c'était "Number" qui était sélectionné pour cette ligne

    Je rappelle que ce n'est rien de bien grave puisqu'ensuite, je peux remettre cette valeur à "Number" sans autres conséquences néfastes, mais c'est juste un comportement troublant à l'utilisation...

    Si quelqu'un pouvait m'indiquer ce que j'ai mal fait... Je vous remercie d'avance

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    On pourrait voir le code de ta classe Renderer qui représente le JComboBox...

    a++

  3. #3
    Membre confirmé Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Points : 554
    Points
    554
    Par défaut
    C'est l'équivalent de ces 2 lignes du tutorial :

    sportColumn.setCellEditor(new DefaultCellEditor(comboBox));

    //Set up tool tips for the sport cells.
    DefaultTableCellRenderer renderer =
    new DefaultTableCellRenderer();

    Je cherche actuellement un code min de l'erreur...

  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Et quel est le type des objets Java stocké dans cette colonne ???

    a++

  5. #5
    Membre confirmé Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Points : 554
    Points
    554
    Par défaut
    Bon en mixant le code de sun et le miens, je suis arrivé a une version plus petite mais qui buggue toujours. La voici :

    Les types manipulés :

    P1PropertyType :
    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
     
    public abstract class P1PropertyType {
     
        public static String textProperty = "Text";
        public static String numberProperty = "Number";
     
        private String name;
     
        public P1PropertyType (String n) {
            name = n;
        }
     
        public String getName() {
            return name;
        }
     
        public void setName(String string) {
            name = string;
        }
     
        public String toString () {
            return getName();
        }
     
        // creates a new PropertyType with the type parameter
        static public P1PropertyType createPropertyType (String type) {
            if (type.equals(textProperty)) {
                return new P1TextPropertyType("");
            } else if (type.equals(numberProperty)) {
                return new P1NumberPropertyType("");
            }
            return null;
        }
     
        public abstract String getType ();
    }
    P1TextPropertyType :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public class P1TextPropertyType extends P1PropertyType {
     
        public P1TextPropertyType(String n) {
            super(n);
        }
     
        public String getType() {
            return P1PropertyType.textProperty;
        }
    }
    P1NumberPropertyType :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public class P1NumberPropertyType extends P1PropertyType {
     
        public P1NumberPropertyType(String n) {
            super(n);
        }
     
        public String getType() {
            return P1PropertyType.numberProperty;
        }
    }
    Ma JComboBox :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public class P1JComboBoxPropertyType extends JComboBox {
     
        private static final long serialVersionUID = 1L;
     
        public P1JComboBoxPropertyType() {
            super();
            DefaultComboBoxModel model = new DefaultComboBoxModel();
            model.addElement(new P1TextPropertyType(P1PropertyType.textProperty));
            model.addElement(new P1NumberPropertyType(P1PropertyType.numberProperty));
            this.setModel(model);
        }    
    }
    Le code de sun repris et arrangé pour utiliser mes classes (et qui buggue donc) :
    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
    94
    95
    96
    97
    98
     
    public class TableRenderDemo extends JPanel {
     
        private static final long serialVersionUID = 1L;
     
        public TableRenderDemo() {
            super(new GridLayout(1,0));
     
            JTable table = new JTable(new MyTableModel());
            setUpSportColumn(table, table.getColumnModel().getColumn(1));
            add(table);
        }
     
        public void setUpSportColumn(JTable table,
                                     TableColumn sportColumn) {
            P1JComboBoxPropertyType comboBox = new P1JComboBoxPropertyType();
            sportColumn.setCellEditor(new DefaultCellEditor(comboBox));
        }
     
        class MyTableModel extends AbstractTableModel {
     
            private static final long serialVersionUID = 1L;
            private String[] columnNames = {"Name","Type"};
            private Object[] data = {
                new P1TextPropertyType(""),
                new P1NumberPropertyType(""),
                new P1TextPropertyType(""),
                new P1NumberPropertyType(""),
                new P1TextPropertyType("")
            };
     
            public final Object[] longValues = {"None of the above"};
     
            public int getColumnCount() {
                return columnNames.length;
            }
     
            public int getRowCount() {
                return data.length;
            }
     
            public String getColumnName(int col) {
                return columnNames[col];
            }
     
            public Object getValueAt(int arg0, int arg1) {
                P1PropertyType pt = (P1PropertyType)data[arg0];
                switch (arg1) {
                    case 0 :
                        return pt.getName();
                    case 1 :
                        return pt.getType();
                }
                return null;
            }
     
            public Class<?> getColumnClass(int c) {
                return getValueAt(0, c).getClass();
            }
     
            public boolean isCellEditable(int row, int col) {
                    return true;
            }
     
            public void setValueAt(Object value, int row, int col) {
                P1PropertyType pt = (P1PropertyType)data[row];
                switch (col) {
                    case 0 :
                        pt.setName((String)value);
                        break;
                    case 1 :
                        String n = pt.getName();
                        pt = P1PropertyType.createPropertyType(((P1PropertyType)value).getType());
                        pt.setName(n);
                        data[row] = pt;
                        break;
                }
                fireTableCellUpdated(row, col);
            }
        }
     
        private static void createAndShowGUI() {
            JFrame frame = new JFrame("TableRenderDemo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            TableRenderDemo newContentPane = new TableRenderDemo();
            frame.setContentPane(newContentPane);
            frame.pack();
            frame.setVisible(true);
        }
     
        public static void main(String[] args) {
            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
            });
        }
    }
    Voila, avec ce code, j'ai le même comportement dérangeant... Je pense que mon erreur provient de la méthode "setValueAt", mais je ne comprends pas... Merci si vous avez une idée (ou si vous savez carrément )

  6. #6
    Membre confirmé Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Points : 554
    Points
    554
    Par défaut
    L'erreur ne vient pas de mon setValueAt puisque si je met rien dans ce code, j'obtiens toujours le même problème...

  7. #7
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Apparemment tu n'as pas implémenté la méthode equals() dans tes classes.
    Tu dois surement manipulé différentes instances de tes classes, et deux instances identiques pour toi ne le sont pas pour ton application. Lorsque ton CellEditor initialise la valeur par défaut de ta JCombox avec setSelectedItem(), elle ne la retrouve pas dans la liste puis equals renvoit toujours false...

    Tu peux vérifier cela avec le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    P1TextPropertyType p1 = new P1TextPropertyType ("hello");
    P1TextPropertyType p2 = new P1TextPropertyType ("hello");
     
    System.out.println( p1.equals(p2) ); // affiche false
    Il faut donc que tu implémentes equals(), ce qui pourrait donner dans la classe P1PropertyType :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public boolean equals(Object o) {
        if (this==o) {
            return true;
        }
     
        if (o instanceof P1PropertyType) {
            P1PropertyType p = (P1PropertyType) o;
     
            return getName().equals(p.getName())
                && getType().equals(p.getType());
        }
        return false;
    }
    Enfin je te conseille d'implémenter également la méthode hashCode() (même si tu n'en as pas besoin ici), et de lire le post suivant :
    redéfinition de equals

    a++

  8. #8
    Membre confirmé Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Points : 554
    Points
    554
    Par défaut
    Merci beaucoup pour cette réponse ! En effet je pense que tu as mis le doigt sur le problème, mais cela ne suffit pas

    En effet, en redéfinnissant la méthode equals, j'obtenais toujours le même comportement. Suite à tes explications, j'ai donc peaufiner la recherche et j'en suis arrivé à une solution de ce type (qui marche) :

    Ma JComboBox :
    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
    public class P1JComboBoxPropertyType extends JComboBox {
     
        private static final long serialVersionUID = 1L;
     
        public P1JComboBoxPropertyType() {
            super();
            DefaultComboBoxModel model = new DefaultComboBoxModel();
            model.addElement(new P1TextPropertyType(P1PropertyType.textProperty));
            model.addElement(new P1NumberPropertyType(P1PropertyType.numberProperty));
            this.setModel(model);
        }
     
        private P1PropertyType getItemWithType (String type) {
            int nbItems = getItemCount();
            for (int i=0; i<nbItems; i++) {
                P1PropertyType pt = (P1PropertyType)getItemAt(i);
                if (pt.getType().equals(type))
                    return pt;
            }
            return null;
        }
     
        public void setSelectedItem(Object anObject) {
            try {
                super.setSelectedItem(getItemWithType(((P1PropertyType)anObject).getType()));
            }catch (Exception e) {
                super.setSelectedItem(getItemWithType((String)anObject));
            }
        }
     
    }
    cela donne le comportement correct : ceci fonctionnant, cela signifie que tantôt le setSelectedItem de ma jcombobox est appelé avec un coup une string, un coup un P1PropertyType (ce qui explique pourquoi la simple redéfinition de equals ne fonctionnait pas). Il est donc clair et net qu'il y a quelque chose que je fais mal, car il n'est pas normal que je bidouille ainsi pour réparer mon bug (j'aimerai que le setSelectedItem n'ai lieu qu'avec des P1PropertyType). Le problème est que je ne maitrise pas encore le fonctionnement d'une JComboBox dans une JTable (méthodes invoquées a tel ou tel moment...) et que donc je ne vois pas ou j'ai faux...

    Un dernier petit coup de pouce me rendrait un grand service !
    (car oui comme ça ça marche, mais c'est pas propre du tout )

    En tout cas un grand merci pour avoir touché le problème

  9. #9
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    A mon avis le problème vient de ton TableModel...
    As-tu implémenté la méthode setValueAt() ? Si oui comment ?

    a++

  10. #10
    Membre confirmé Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Points : 554
    Points
    554
    Par défaut
    Définition de l'objet "data" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
            private Object[] data = {
                new P1TextPropertyType(""),
                new P1NumberPropertyType(""),
                new P1TextPropertyType(""),
                new P1NumberPropertyType(""),
                new P1TextPropertyType("")
            };
    méthode getValueAt de ma TableModel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
            public Object getValueAt(int arg0, int arg1) {
                P1PropertyType pt = (P1PropertyType)data[arg0];
                switch (arg1) {
                    case 0 :
                        return pt.getName();
                    case 1 :
                        return pt.getType();
                }
                return null;
            }
    méthode setValueAt de ma TableModel :
    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
     
            public void setValueAt(Object value, int row, int col) {
                P1PropertyType pt = (P1PropertyType)data[row];
                switch (col) {
                    case 0 :
                        pt.setName((String)value);
                        break;
                    case 1 :
                        String n = pt.getName();
                        pt = P1PropertyType.createPropertyType(((P1PropertyType)value).getType());
                        pt.setName(n);
                        data[row] = pt;
                        break;
                }
                fireTableCellUpdated(row, col);
            }

  11. #11
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Dans getValueAt(), tu renvoit directement le type (et donc une String) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    case 1 :
        return pt.getType();
    Et c'est cela qui est passé à ton JComboBox...
    Il faudrait que tu retournes directement pt, mais du coups tu dois utiliser un ListCellRenderer sur ta JComboBox pour que l'affichage soit correcte avec le type et non pas le nom de ta propriétée...


    Ou sinon tu peux carrément adapter equals() pour qu'elle traite les String d'une manière particulière :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public boolean equals(Object o) {
        if (this==o) {
            return true;
        }
        String type = null;
     
        if (o instanceof P1PropertyType) {
            type = ( (P1PropertyType) o ).getType();
        } else if (o instanceof String){
            type = (String) o;
        }
           return getType().equals(type);
    }
    a++

  12. #12
    Membre confirmé Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Points : 554
    Points
    554
    Par défaut
    Et bien merci beaucoup pour ton implication dans mon problème adiGuba

    J'ai maintenant mieux compris ce qui n'allait pas

    La méthode que j'aurai préféré est celle consistant a redéfénir le ListCellRenderer de ma JComboBox mais je n'ai pas réussi a le faire correctement (la méthode a redéfinir doit renvoyer un composant, or me concernant c'est juste la chaine à afficher que je voudrais changer, pas de refaire tout le composant graphique...). La méthode du equals reste la plus simple

    Merci beaucoup pour ton aide et merci à ce Forum

  13. #13
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Claythest
    La méthode que j'aurai préféré est celle consistant a redéfénir le ListCellRenderer de ma JComboBox mais je n'ai pas réussi a le faire correctement (la méthode a redéfinir doit renvoyer un composant, or me concernant c'est juste la chaine à afficher que je voudrais changer, pas de refaire tout le composant graphique...). La méthode du equals reste la plus simple
    Tu peux hériter de DefaultListCellRenderer qui fera le boulot à ta place... Il ne te reste plus qu'a remplacer le paramètre value par la valeur de getType() :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class P1PropertyTypeListCellRenderer extends DefaultListCellRenderer {
     
        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index,
                boolean isSelected, boolean cellHasFocus) {
            String type = "";
            if (value instanceof P1PropertyType) {
                type = ((P1PropertyType)value).getType();
            }
            return super.getListCellRendererComponent(list, type, index, isSelected, cellHasFocus);
        }
    }
    a++

  14. #14
    Membre confirmé Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Points : 554
    Points
    554
    Par défaut
    Et bien merci pour tout !
    (j'y avais pas pensé )

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

Discussions similaires

  1. Gxt: Problème lors d'une édition dans une EditorGrid
    Par miragul dans le forum GWT et Vaadin
    Réponses: 2
    Dernier message: 07/03/2013, 17h05
  2. Réponses: 2
    Dernier message: 27/03/2009, 11h30
  3. [JTable] Problème lors de la création via Vector
    Par Shurka dans le forum Composants
    Réponses: 6
    Dernier message: 13/08/2007, 12h48
  4. [JTable]évènement lors de l'édition ?
    Par Claythest dans le forum Composants
    Réponses: 1
    Dernier message: 03/05/2007, 10h36
  5. Réponses: 9
    Dernier message: 12/06/2006, 09h59

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