Bonjour,
J'ai besoin d'aide sur un problème swing...
Je souhaite mettre un comboBox 'autocomplétable' dans une JTable.
J'ai récupéré le code d'une JComboBox autocomplétable mais je n'arrive pas à l'intégrer à ma JTable.
Ci dessous le code :
La classe principale (déclaration de la table) et la ComboBox :
L'éditeur de la combo :
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 import javax.swing.DefaultCellEditor; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.TableColumn; public class myJCB extends JComboBox{ public myJCB(Object[] pTabObj) { super(pTabObj); this.setEditor(new myAutoCompleteEditor(this, true)); } public static void main(String[] args) { JFrame f = new JFrame("Table Combo"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); String[] choix = {"ab", "abc", "ac", "aca", "acb", "ace", "acf", "acft", "acfty", "acfs", "ar", "are", "arez", "b", "bb"}; JTable myTable1 = new JTable(2, 2); myJCB box1 = new myJCB(choix); box1.setEditable(true); TableColumn maColonne1 = myTable1.getColumnModel().getColumn(0); maColonne1.setCellEditor(new DefaultCellEditor(box1)); maColonne1.setHeaderValue("AutoComp"); JScrollPane myScrollPane = new JScrollPane(myTable1); f.getContentPane().add(myScrollPane); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); } }
Et finalement le code que j'ai récupéré pour l'autocomplétion :
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 import java.awt.Component; import javax.swing.JComboBox; import javax.swing.JTextField; import javax.swing.plaf.basic.BasicComboBoxEditor; /* * AutoCompleteEditor.java */ public class myAutoCompleteEditor extends BasicComboBoxEditor { private JTextField editor = null; public myAutoCompleteEditor(JComboBox combo, boolean caseSensitive){ super(); editor = new myAutoCompleteEditorComponent(combo, caseSensitive); } public Component getEditorComponent(){ return editor; } }
Ce code fonctionne bien lorsque le combo n'est pas dans une table mais lorsqu'il est dans la table j'ai une erreur sur l'instruction
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 import javax.swing.JComboBox; import javax.swing.JTextField; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.PlainDocument; /* * AutoCompleteEditorComponent.java */ public class myAutoCompleteEditorComponent extends JTextField { JComboBox combo = null; boolean caseSensitive = false; public myAutoCompleteEditorComponent(JComboBox combo, boolean caseSensitive){ super(); this.combo = combo; this.caseSensitive = caseSensitive; } protected Document createDefaultModel(){ return new PlainDocument() { public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { if (str == null || str.length() == 0) return; int size = combo.getItemCount(); String text = getText(0, getLength()); for (int i = 0; i < size; i++) { String item = combo.getItemAt(i).toString(); if (getLength() + str.length() > item.length()) continue; if (!caseSensitive){ if ((text + str).equalsIgnoreCase(item)){ combo.setSelectedIndex(i); if (!combo.isPopupVisible()) combo.setPopupVisible(true); super.remove(0, getLength()); super.insertString(0, item, a); return; }else if (item.substring(0, getLength() + str.length()).equalsIgnoreCase(text + str)){ combo.setSelectedIndex(i); if (!combo.isPopupVisible()) combo.setPopupVisible(true); super.remove(0, getLength()); super.insertString(0, item, a); return; } }else if (caseSensitive){ if ((text + str).equals(item)){ combo.setSelectedIndex(i); if (!combo.isPopupVisible()) combo.setPopupVisible(true); super.remove(0, getLength()); super.insertString(0, item, a); return; }else if (item.substring(0, getLength() + str.length()).equals(text + str)){ combo.setSelectedIndex(i); if (!combo.isPopupVisible()) combo.setPopupVisible(true); super.remove(0, getLength()); super.insertString(0, item, a); return; } } } } }; } }
qui me renvoie l'erreur suivante lorsque je tape une touche :
Code : Sélectionner tout - Visualiser dans une fenêtre à part combo.setPopupVisible(true);
Lorsque je supprime la ligne qui pose problème je n'ai plus d'erreur mais je ne peux taper qu'un seul caractère à la fois dans le champ. (Il faut que je reclique sur la zone pour pouvoir en saisir un autre...) Lorsque je supprime la ligne combo.setSelectedIndex(i) je peux taper plusieurs caractères (mais la liste ne se positionne pas => normal). J'imagine que l'instruction setSelectedIndex doit rendre le focus à la table.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 Exception in thread "AWT-EventQueue-0" java.awt.IllegalComponentStateException: component must be showing on the screen to determine its location at java.awt.Component.getLocationOnScreen_NoTreeLock(Component.java:1680) at java.awt.Component.getLocationOnScreen(Component.java:1654) at javax.swing.JPopupMenu.show(JPopupMenu.java:945) at javax.swing.plaf.basic.BasicComboPopup.show(BasicComboPopup.java:191) at javax.swing.plaf.basic.BasicComboBoxUI.setPopupVisible(BasicComboBoxUI.java:823) at javax.swing.JComboBox.setPopupVisible(JComboBox.java:790) at myAutoCompleteEditorComponent$1.insertString(myAutoCompleteEditorComponent.java:54)
Apparemment c'est un problème de focus, j'ai fait plusieurs tests mais je ne maîtrise pas suffisamment Swing ...
Quelqu'un aurait-il une solution à me proposer ou une piste que je pourrai explorer ?
RQ : J'ai cru comprendre qu'il existe un composant swingx qui fait ce travail mais je ne souhaite pas ajouter des bibliothèques supplémentaires.
Partager