JComboBox ! C'est la merde !

JComboBox ! C'est la merde ! - Java - Programmation

Marsh Posté le 18-09-2002 à 03:57:28    

J'ai un problème crucial pour mon IHM. Le truc c'est que j'ai une liste d'objets. J'ai plusieurs vues de cette liste, sous forme de JComboBox. Alors comme j'ai des exceptions à la con qui sont lancées de partout avec mon programme j'ai fait ce test qui est le plus concluant que j'ai obtenu, à un défaut près : le REFRESH qui est pourri. Compilez et jugez plutôt (s'il vous plait ! ! ! [:ddr555])
 

Code :
  1. import java.awt.*;
  2. import java.awt.event.*;
  3. import java.util.Vector;
  4. import javax.swing.*;
  5. public class ComboBoxTest2 extends JFrame implements ActionListener {
  6. private JComboBox comboBox1;
  7. private JComboBox comboBox2;
  8. private JComboBox comboBox3;
  9. private JButton button = new JButton("Greetings" );
  10. private Vector vector;
  11. public ComboBoxTest2() {
  12.  setTitle("Greetings App" );
  13.  getContentPane().setLayout(new FlowLayout());
  14.  Vector vector = new Vector();
  15.  vector.add("Coucou" );
  16.  vector.add("Hello" );
  17.  vector.add("Guten Tag" );
  18.  comboBox1 = new JComboBox(vector);
  19.  comboBox2 = new JComboBox(vector);
  20.  comboBox3 = new JComboBox(vector);
  21.  getContentPane().add(comboBox1);
  22.  getContentPane().add(comboBox2);
  23.  getContentPane().add(comboBox3);
  24.  getContentPane().add(button);
  25.  button.addActionListener(this);
  26.  setVisible(true);
  27.  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  28.  pack();
  29. }
  30. public static void main(String[] args) {
  31.  new ComboBoxTest2();
  32. }
  33. public void actionPerformed(ActionEvent e) {
  34.  if (e.getSource() == button) {
  35.   comboBox1.addItem("Hola" );
  36.  }
  37. }
  38. }


 
Le programme crée trois combos basées sur un Vector de String. Le bouton Greetings ajoute une String à la combo de gauche (comboBox1). Les autres ont des problèmes de refresh, mais se mettent aussi à jour (c'est cette fonctionnalité qui m'intéresse).
 
Autre question, pourquoi je ne peux pas ajouter directement les éléments à mon vector ? ça lance des tas d'exceptions ! Y a t'il un moyen ?


---------------
Le site de ma maman
Reply

Marsh Posté le 18-09-2002 à 03:57:28   

Reply

Marsh Posté le 18-09-2002 à 09:01:59    

Yooo!!
Bah, en fait, j'ai pas tout compris à tes souçis : ici, àça a l'air de marcher,comme il faut, je vois pas trop où est ton problème...
Et sinon, comment ça, tu as des exceptions quand tu ajoutes des éléments à ton vecteur?? quelles exceptions??
 
Alors, sinon, un truc que tu pourrais essayer, c'est de virer le vecteur, et d'untiliser à la place, un DefaultComboBoxModel : tu instancies tes 3 JComboBox en leur passant cet objet, et dans la méthode actionPerformed(ActionEvent e), tu ajoutes ton élément au modèle (il y a des méthodes pour ça, voir Javadoc) Je dis ça, parce que normalement, le modèle gère la mise à jour des Combobox..
 
Ouala..

Reply

Marsh Posté le 18-09-2002 à 10:00:27    

gfive a écrit a écrit :

Yooo!!
Bah, en fait, j'ai pas tout compris à tes souçis : ici, àça a l'air de marcher,comme il faut, je vois pas trop où est ton problème...
Et sinon, comment ça, tu as des exceptions quand tu ajoutes des éléments à ton vecteur?? quelles exceptions??
 
Alors, sinon, un truc que tu pourrais essayer, c'est de virer le vecteur, et d'untiliser à la place, un DefaultComboBoxModel : tu instancies tes 3 JComboBox en leur passant cet objet, et dans la méthode actionPerformed(ActionEvent e), tu ajoutes ton élément au modèle (il y a des méthodes pour ça, voir Javadoc) Je dis ça, parce que normalement, le modèle gère la mise à jour des Combobox..
 
Ouala..




 
Son code marche mais au depart il ne voulait pas faire de additem sur la combo, mais uniquement ajouter des elements a son vecteur.
 
Le probleme avec ceci est (AMHA a verifier avec les sources) que lors de l'initialisation de la combo en lui passant un vecteur, le constructeur va prendre tous les element s contenus dans le vecteur et en fait un datamodel. Lors de la modification du vecteur, celui-ci ne correspond plus au modele...
 
La solution est de faire les manips directement sur le comboboxmodel ce qui comme tu le dis force le refresh de la GUI.
 

Reply

Marsh Posté le 18-09-2002 à 10:04:08    

Bon, je vais voir si c'est jouable d'ajouter mes gros objets (et oui, c'est pas des String en vrai) au Model.
 
L'effet que vous auriez du voir, c'est la liste qui se rezize, mais les élements ne sont pas visibles (Win2K + J2SDK 1.4).


---------------
Le site de ma maman
Reply

Marsh Posté le 18-09-2002 à 10:13:01    

C'est effectivement la solution : utiliser une instance de ComboBoxModel plutôt que Vector.

Reply

Marsh Posté le 18-09-2002 à 10:27:15    

Justement, là je viens de faire un test et ça marche, cependant, si je veux sur pression du bouton faire afficher le contenu du vector, je prends la même floppée d'exceptions à laquelle je faisais mention.
 
Jugez plutôt :
 

Code :
  1. import java.awt.*;
  2. import java.awt.event.*;
  3. import java.util.Vector;
  4. import java.util.Iterator;
  5. import javax.swing.*;
  6. public class ComboBoxTest3 extends JFrame implements ActionListener {
  7. private JComboBox comboBox1;
  8. private JComboBox comboBox2;
  9. private JComboBox comboBox3;
  10. private JButton button = new JButton("Greetings" );
  11. private DefaultComboBoxModel model;
  12. private Vector vector;
  13. public ComboBoxTest3() {
  14.  setTitle("Greetings App" );
  15.  getContentPane().setLayout(new FlowLayout());
  16.  Vector vector = new Vector();
  17.  vector.add("Coucou" );
  18.  vector.add("Hello" );
  19.  vector.add("Guten Tag" );
  20.  model = new DefaultComboBoxModel(vector);
  21.  comboBox1 = new JComboBox(model);
  22.  comboBox2 = new JComboBox(model);
  23.  comboBox3 = new JComboBox(model);
  24.  getContentPane().add(comboBox1);
  25.  getContentPane().add(comboBox2);
  26.  getContentPane().add(comboBox3);
  27.  getContentPane().add(button);
  28.  button.addActionListener(this);
  29.  setVisible(true);
  30.  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  31.  pack();
  32. }
  33. public static void main(String[] args) {
  34.  new ComboBoxTest3();
  35. }
  36. public void actionPerformed(ActionEvent e) {
  37.  if (e.getSource() == button) {
  38.   model.addElement("Hola" );
  39.   Iterator i = vector.iterator();
  40.   while (i.hasNext()) {
  41.    System.out.println(i.next());
  42.   }
  43.  }
  44. }
  45. }

j'ai mis en gras les changements. Sinon, ben les exceptions, y en a trop. Les premières dans l'ordre :
 
NullPointerException at ComboBoxTest3.actionPerformed(ComboBoxTest3.java)
AbstractButton.fireActionPerformed(AbstractButton.java)
 
Et tous les composants Swing y passent ensuite.


Message édité par Cherrytree le 18-09-2002 à 10:27:42

---------------
Le site de ma maman
Reply

Marsh Posté le 18-09-2002 à 10:34:07    

quelle ligne ...  
 


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 18-09-2002 à 10:43:05    

DarkLord a écrit a écrit :

quelle ligne ...  
 
 



47 mais bon c'était pas dur à deviner. C'est la ligne : Iterator i = ...


---------------
Le site de ma maman
Reply

Marsh Posté le 18-09-2002 à 10:49:01    

remplace  Vector vector  .... par vector dans ton constructeur ca ira mieux ;)
 
(faut dormir)


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 18-09-2002 à 10:52:24    

DarkLord a écrit a écrit :

remplace  Vector vector  .... par vector dans ton constructeur ca ira mieux ;)
 
(faut dormir)



Putain ! J'en reviens pas ! C'était ça depuis le début ! Arrgh ! Merci en tous cas !


---------------
Le site de ma maman
Reply

Marsh Posté le 18-09-2002 à 10:52:24   

Reply

Marsh Posté le 18-09-2002 à 10:58:45    

c'est normal qd tu travailles avec un éditeur simple et que tu ne dors pas bcp :)


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 18-09-2002 à 11:11:14    

DarkLord a écrit a écrit :

c'est normal qd tu travailles avec un éditeur simple et que tu ne dors pas bcp :)



Promis, j'essayerai IntelliJ


---------------
Le site de ma maman
Reply

Marsh Posté le 18-09-2002 à 11:27:55    

ce n'est pas ce que je voulais dire  :ange: mais il est vrai que c'est super chouette d'éviter ce genre de petit problème si facilement (re  :ange: )


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 18-09-2002 à 11:31:22    

y a un autre truc bizarre :  
 

Code :
  1. public void actionPerformed(ActionEvent e) {
  2.         if (e.getSource() == button) {
  3.            model.addElement("Hola" );
  4.            Iterator i = vector.iterator();
  5.            while (i.hasNext()) {
  6.               System.out.println(i.next());
  7.            }
  8.         }
  9.      }


tu ajoutes un truc dans ton model, puis tu itères sur le vector ...


Message édité par benou le 18-09-2002 à 11:31:53
Reply

Marsh Posté le 18-09-2002 à 11:33:24    

ah ouais tiens


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 18-09-2002 à 11:41:14    

ça c'est voulu. Je tiens à manipuler le Vector (au départ ç'aurait dû être une ArrayList, mais bon pas le temps). C'est sur le contenu de ce Vector que je dois appliquer un algo maison. Franchement ça me ferait bizzare de lui passer un DefaultComboBoxModel. Sachant que c'est quand même très lié à la ComboBox et qu'on ne peut pas itérer dessus. ça vous gene à ce point ?


---------------
Le site de ma maman
Reply

Marsh Posté le 18-09-2002 à 11:43:33    

En fait, maintenant que DarkLord a débuggué mon code, je peux ajouter au Vector directement et les combos sont mises à jour. C'est cool.


---------------
Le site de ma maman
Reply

Marsh Posté le 18-09-2002 à 12:24:19    

ouais, mais c'est un coup de bol, en fait : c'est parce que dans le code de JComboBox, le constructeur avec un vecteur appelle le constructeur de DefaultComboBoxModel qui prend un vecteur en argument, et que ce constructeur de DefaultComboBoxModel contient ça :  
 
 

Code :
  1. public DefaultComboBoxModel(Vector v) {
  2.         objects = v;
  3.         if ( getSize() > 0 ) {
  4.             selectedObject = getElementAt( 0 );
  5.         }
  6.     }

 
 
donc, le modèle a une référence sur le vecteur...C'est d'ailleurs assez étonnant : c'est qqpart entre le bug et la feature, ce truc là...

Reply

Marsh Posté le 18-09-2002 à 12:34:53    

gfive a écrit a écrit :

donc, le modèle a une référence sur le vecteur...C'est d'ailleurs assez étonnant : c'est qqpart entre le bug et la feature, ce truc là...




 
 :jap: [:prosterne]


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 18-09-2002 à 13:07:39    

gfive a écrit a écrit :

ouais, mais c'est un coup de bol, en fait : c'est parce que dans le code de JComboBox, le constructeur avec un vecteur appelle le constructeur de DefaultComboBoxModel qui prend un vecteur en argument, et que ce constructeur de DefaultComboBoxModel contient ça :  
 
 

Code :
  1. public DefaultComboBoxModel(Vector v) {
  2.         objects = v;
  3.         if ( getSize() > 0 ) {
  4.             selectedObject = getElementAt( 0 );
  5.         }
  6.     }

 
 
donc, le modèle a une référence sur le vecteur...C'est d'ailleurs assez étonnant : c'est qqpart entre le bug et la feature, ce truc là...



[:zebra33] Pas sûr d'avoir tout capté, mais c'est normal, j'ai les yeux qui fatiguent.


---------------
Le site de ma maman
Reply

Marsh Posté le 18-09-2002 à 14:17:40    

gfive a écrit a écrit :

 
donc, le modèle a une référence sur le vecteur...C'est d'ailleurs assez étonnant : c'est qqpart entre le bug et la feature, ce truc là...




mouais .... [:wam]
 
edit : d'autant plus que dans la javadoc ils disent :
 

Citation :

public DefaultComboBoxModel(Vector v)
 
Constructs a DefaultComboBoxModel object initialized with a vector.


Message édité par benou le 18-09-2002 à 14:25:08
Reply

Marsh Posté le 18-09-2002 à 14:24:15    

Cherrytree a écrit a écrit :

Franchement ça me ferait bizzare de lui passer un DefaultComboBoxModel. Sachant que c'est quand même très lié à la ComboBox et qu'on ne peut pas itérer dessus. ça vous gene à ce point ?




tatata !!!
faut penser objet, cherry !
 
le ComboBoxModel c'est une interface. c'est de ca dont la JComboBox a besoin.
 
par exemple, tu peux faire un objet MaListe qui gérite de ArrayList et qui implémente ComboBoxModel, et même si tu le veux, qui se sert d'un DefaultComboBoxModel par délégation (ou mieux d'une sous classe de AbstractListModel que tu écriras sous forme de inner classe privée et qui lira dans ton objet MaListe).
 
c'est la façon propre mais complexe de résoudre le problème, je pense ...

Reply

Marsh Posté le 18-09-2002 à 14:24:53    

Bah, j'ai pas tout mis le code des classes, parce que c'est gros, mais bon, vopilà :  
 
 

Code :
  1. public class DefaultComboBoxModel implements ComboBoxModel {
  2. private Vector objects;
  3. ....
  4. public DefaultComboBoxModel(Vector v) {
  5.     objects = v;
  6.      ....
  7. }

 
 
 
et  
 

Code :
  1. public class JComboBox extends Component {
  2.   ....
  3.   public JComboBox(ComboBoxModel model) {
  4.         ....
  5.   }
  6.   public JCombobox(Vector v) {
  7.        this(new DefaultComboBoxModel(v));
  8.   }
  9. }

 
 
Tu piges???Je dis donc que c'est limite buggé, parce que nulle part dans la doc, il n'est indiqué que quand tu appelles le constructeur de JComboBox avec un Vector, le Vector est utilisé comme modèle.....Et c'est assez troublant, comme truc, la preuve, ça amène des comportements  difficilement explicables.

Reply

Marsh Posté le 18-09-2002 à 14:26:09    

gfive a écrit a écrit :

 
Tu piges???Je dis donc que c'est limite buggé, parce que nulle part dans la doc, il n'est indiqué que quand tu appelles le constructeur de JComboBox avec un Vector, le Vector est utilisé comme modèle.....Et c'est assez troublant, comme truc, la preuve, ça amène des comportements  difficilement explicables.




ouep ! voir mon edit du dessus ...


Message édité par benou le 18-09-2002 à 14:26:14
Reply

Marsh Posté le 18-09-2002 à 14:44:09    

:ouch:  
 
gfive tu n'ouvrirais pas un ticket chez SUN avec cette info ou du moins voir si c'est déjà répertorié?


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 18-09-2002 à 14:49:41    

si je dis que ça me parait logique je me fais taper dessus?
 
edit: dans la doc du constructeur sans argument:

Citation :

Creates a JComboBox with a default data model. The default data model is an empty list of objects. Use addItem to add items. By default the first item in the data model becomes selected.


 
ça me parait donc logique que ça soit le meme comportement tant que tu ne passes pas de modele, non?


Message édité par --greg-- le 18-09-2002 à 14:51:57

---------------
#19b | Mardi 18 Février 2003 - nous fêtons les Bernadette | contre le fleur icq!
Reply

Marsh Posté le 18-09-2002 à 15:23:38    

Bah, ça, on te l'accorde...Mais si tu veux, il est pas normal que quand tu passes un Vector au constructeur, il utilise l'INSTANCE que tu lui as passé, pour créer son modèle....donc, si tu modifies ton Vecteur, ta combobox sera influencée, et vice versa....Et ça, c'est pas indiqué explicitement dans la Javadoc!! Normalement, le comportement décrit par Cherrytree est pas celui auquel on doit s'attendre!!
 
C un peu comme si tu faisais ça :  
 
 

Code :
  1. String toto="toto";
  2. JButton button = new JButton(toto);
  3. JButton button2 = new JButton(toto);

 
 
Là, si je modifie la valeur de la chaîne toto, les labels des boutons ne changent pas, et c'est ce qu'on est sensé attendre....De plus, si tu changes le label de button, tu t'attends pas à voir changer celui de button2, or, avec le coup du vecteur, c'est ce que l'on observe....C'est un comportement qu'on peut vouloir, mais SI on le veut, on DOIT utiliser un ComboBoxModel, qui est explicitement fairt pour ça..
 
Ouala..


Message édité par gfive le 18-09-2002 à 15:24:12
Reply

Marsh Posté le 18-09-2002 à 15:24:51    

ha okie !
 
a tout hasard, ça fait ça aussi quand un passe un array[] ?
 
edit: euh ben non, ça le fait pas.


Message édité par --greg-- le 18-09-2002 à 15:26:12

---------------
#19b | Mardi 18 Février 2003 - nous fêtons les Bernadette | contre le fleur icq!
Reply

Marsh Posté le 18-09-2002 à 15:28:37    

DarkLord a écrit a écrit :

 :ouch:  
 
gfive tu n'ouvrirais pas un ticket chez SUN avec cette info ou du moins voir si c'est déjà répertorié?




 
Bah, pôs l'temps, trop, là :D

Reply

Marsh Posté le 18-09-2002 à 16:33:24    

Cette fois ci j'ai complètement compris l'explication de gfive et je suis d'accord avec lui. [:plat00n] gfive.


---------------
Le site de ma maman
Reply

Marsh Posté le 18-09-2002 à 17:47:51    

--greg-- a écrit a écrit :

ha okie !
 
a tout hasard, ça fait ça aussi quand un passe un array[] ?
 
edit: euh ben non, ça le fait pas.
 




si je me trompe pas, il construit un vecteur à partir du array puis construit le defaultComboBoxModel avec ce vecteur là. Comme le vecteur fait une copie des références des éléments de ton tableau, y a pas de problème

Reply

Marsh Posté le 18-09-2002 à 18:22:33    

benou a écrit a écrit :

 
si je me trompe pas, il construit un vecteur à partir du array puis construit le defaultComboBoxModel avec ce vecteur là. Comme le vecteur fait une copie des références des éléments de ton tableau, y a pas de problème



tout à fait
euh mais il copie les elements eux memes, par leur reference n'est-ce pas...
enfin  :pt1cable: bref si je change mon array, mon JComboBox va pas bouger...


---------------
#19b | Mardi 18 Février 2003 - nous fêtons les Bernadette | contre le fleur icq!
Reply

Marsh Posté le 18-09-2002 à 18:32:43    

--greg-- a écrit a écrit :

tout à fait
euh mais il copie les elements eux memes, par leur reference n'est-ce pas...
enfin  :pt1cable: bref si je change mon array, mon JComboBox va pas bouger...




ben si, il copie les référence, il clone pas les objets ...
 
si tu changes ton tableau, la conbo bougera pas. prce qontre, si tu changes un objet du tableau et que tu update la combo, la modif devrait s'afficher.

Reply

Marsh Posté le 18-09-2002 à 18:36:29    

euh ha oui, ça y est la piece est tombée.


---------------
#19b | Mardi 18 Février 2003 - nous fêtons les Bernadette | contre le fleur icq!
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed