Bonjour à tous,

Je suis en train de coder un composant me permettant de faire de l’auto-complétion. Il est composé d'un JTextField pour l'entrée utilisateur, et d'une JListe qui affiche des propositions en fonction de ce que l'utilisateur a tapé. Cette JListe s'affiche en dessous du JTextField seulement si des propositions sont dispos. Le problème est que cette apparition/disparition de la Jliste déplace les autres composants graphiques qui peuvent être présent. Je souhaiterais que cette Jliste ai le même comportement que la liste des choix qui apparaît dans une combobox, c'est à dire qu'elle passe au dessus des composants situés en dessous sans en altérer leur position.
C'est possible?

Voilà la classe du composant qui permet également de le tester (pas encore terminé)
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
 
public class AutoCompleteTextField extends JPanel {
 
    //Liste composée de tous les objets disponibles
    private List<?> _listAllObjects; 
 
    //Liste composée de tous les objets disponibles sous format String
    private List<String> _listAllObjectsToString = new ArrayList<String>(); 
 
    //Liste de propositions des objets sous format String
    private List<String> _listObjetcToStringProposed = new ArrayList<String>();
 
    //Composants
    private JList _jlistPropositions;
    private JTextField _textField;
    private DefaultListModel _objetAAfficher;
    private JScrollPane _scrollPaneListe;
 
    //Listener
    private caretListener _caretListener = new caretListener();
    private keyListener _keyListener = new keyListener();
 
    private boolean _activationCaretListener = true;
 
    public AutoCompleteTextField(List<?> listeChoix) {
	super();
	_listAllObjects = listeChoix;
	init(null);
    }
 
    public AutoCompleteTextField(List<?> listeChoix, String label) {
	super();
	_listAllObjects = listeChoix;
	init(label);
    }
 
 
    private void init(String label){
	//Récupération des objets disponibles sous forme de String
	for (Object objet : _listAllObjects){
	    _listAllObjectsToString.add(objet.toString());
	}
 
	//Initialisation de la liste des objets à proposer
	_listObjetcToStringProposed.addAll(_listAllObjectsToString);
 
	// Configuration du panel
	GridBagLayout gbl = new GridBagLayout();
	this.setLayout(gbl);
	this.setVisible(true);
	this.setOpaque(false);
 
	// Création et Configuration du textField
	_textField = new JTextField(20);
	_textField.addCaretListener(_caretListener);
	_textField.addKeyListener(_keyListener);
 
	// Création du ListModel;
	_objetAAfficher = new DefaultListModel();
 
	// Création de la JList
	_jlistPropositions = new JList(_objetAAfficher);
	_jlistPropositions.setLayoutOrientation(JList.VERTICAL);
	_jlistPropositions.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
	_jlistPropositions.setAutoscrolls(true);
	_jlistPropositions.setVisibleRowCount(7);
	_scrollPaneListe = new JScrollPane(_jlistPropositions);
	_scrollPaneListe.setVisible(false);
 
 
	// Ajout des composants
	GridBagConstraints gbc = new GridBagConstraints();
 
	//Si il faut un label
	if(label != null){
	    gbc.gridx = 0;
	    gbc.gridy = 0;
	    gbc.weightx = 1;
	    gbc.insets = new Insets(0, 0, 0, 5);
	    gbc.anchor = GridBagConstraints.FIRST_LINE_START;
	    this.add(new JLabel(label), gbc);
	}
 
	gbc.gridx = 1;
	gbc.gridy = 0;
	gbc.weightx = 1;
	gbc.weighty = 1;
	gbc.gridwidth = GridBagConstraints.REMAINDER;
	gbc.gridheight = GridBagConstraints.RELATIVE;
	gbc.anchor = GridBagConstraints.LINE_START;
	gbc.insets = new Insets(0, 0, 0, 0);
	gbc.anchor = GridBagConstraints.WEST;
	this.add(_textField, gbc);
 
 
	gbc.gridx = 1;
	gbc.gridy = 1;
	gbc.gridwidth = GridBagConstraints.REMAINDER;
	gbc.gridheight = GridBagConstraints.REMAINDER;
	gbc.anchor = GridBagConstraints.LAST_LINE_START;
	this.add(_scrollPaneListe, gbc);
    }
 
 
    class caretListener implements CaretListener {
	@Override
	public void caretUpdate(CaretEvent e) {
	    if (_activationCaretListener){
		// Récupération de la recherche de l'utilisateur
		String entree = _textField.getText().toUpperCase();
 
		// On parcourt les objets de _listeChoixSourceToString et
		// on supprime de _listeProposition les choix qui ne correspondent pas
		// à la recherche de l'utilisateur
		for (String objet : _listAllObjectsToString) {
		    if (!objet.toUpperCase().contains(entree)) {
			_listObjetcToStringProposed.remove(objet.toString());
		    } else {
			if (!_listObjetcToStringProposed.contains(objet)) {
			    _listObjetcToStringProposed.add(objet.toString());
			}
		    }
		}
 
		// Affichage de la JList seulement si au moins une lettre est renseignée
		if (e.getDot() >= 1 && !_listObjetcToStringProposed.isEmpty())
		    _scrollPaneListe.setVisible(true);	
		else
		    _scrollPaneListe.setVisible(false);
		AutoCompleteTextField.this.updateUI();
 
		// On trie la Jlist des choix à afficher
		Collections.sort(_listObjetcToStringProposed);
 
		// On réaffecte la liste au DefaultListModel
		_objetAAfficher.removeAllElements();
		for (Object objet : _listObjetcToStringProposed) {
		    _objetAAfficher.addElement(objet);
		}
	    }
 
	}
    }
 
    class keyListener implements KeyListener {
	@Override
	public void keyPressed(KeyEvent e) {
	    int index = _jlistPropositions.getSelectedIndex();
	    // Si touche bas
	    if (e.getKeyCode() == 40) {
		index = _jlistPropositions.getSelectedIndex() + 1;
		_jlistPropositions.setSelectedIndex(index);
		_jlistPropositions.ensureIndexIsVisible(index);
	    }
 
	    // Si touche haut
	    else if (e.getKeyCode() == 38) {
		if (_jlistPropositions.getSelectedIndex() != 0) {
		    index = _jlistPropositions.getSelectedIndex() - 1;
		    _jlistPropositions.setSelectedIndex(index);
		    _jlistPropositions.ensureIndexIsVisible(index);
		}
	    }
 
	    // Si touche entrée
	    else if (e.getKeyCode() == 10) {
		String valeurSelectionne = _jlistPropositions.getSelectedValue().toString();
		//On desactive le caretListener pour éviter de refaire une boucle sur les objet
		_activationCaretListener = false;
		_textField.setText(valeurSelectionne);
		_activationCaretListener = true;
		_scrollPaneListe.setVisible(false);
	    }
 
	}
 
	@Override
	public void keyTyped(KeyEvent e) {
	}
 
	@Override
	public void keyReleased(KeyEvent e) {
	}
 
    }
 
    public static void main(String args[]) {
	JFrame frame = new JFrame("Autocomplete");
	frame.setSize(250,300);
	JPanel panel = new JPanel();
	frame.setContentPane(panel);
 
	List listTest = new ArrayList();
	listTest.add("Javadoc");
	listTest.add("JAVA");
	listTest.add("Developpez.net");
	listTest.add("Developpement");
	listTest.add("Analyste");
	listTest.add("Programmeur");
	listTest.add("Energie");
	listTest.add("Coder");
	listTest.add("Eclipse");
	listTest.add("Programmer");
	listTest.add("Analyser");
 
	AutoCompleteTextField acd = new AutoCompleteTextField(listTest);
	panel.add(acd);
	panel.add(new JLabel("text"));
 
	frame.setVisible(true);
    }
 
}