I have a JTextField
for which I\'m hoping to suggest results to match the user\'s input. I\'m displaying these suggestions in a JList
contained within
The technical answer is to set the popup's focusable property to false:
popup.setFocusable(false);
The implication is that the textField has to take over all keyboard and mouse-triggered actions that are normally handled by the list itself, sosmething like:
final JList list = new JList(Locale.getAvailableLocales());
final JPopupMenu popup = new JPopupMenu();
popup.add(new JScrollPane(list));
popup.setFocusable(false);
final JTextField field = new JTextField(20);
Action down = new AbstractAction("nextElement") {
@Override
public void actionPerformed(ActionEvent e) {
int next = Math.min(list.getSelectedIndex() + 1,
list.getModel().getSize() - 1);
list.setSelectedIndex(next);
list.ensureIndexIsVisible(next);
}
};
field.getActionMap().put("nextElement", down);
field.getInputMap().put(
KeyStroke.getKeyStroke("DOWN"), "nextElement");
As your context is very similar to a JComboBox, you might consider having a look into the sources of BasicComboBoxUI and BasicComboPopup.
Edit
Just for fun, the following is not answering the focus question :-) Instead, it demonstrates how to use a sortable/filterable JXList to show only the options in the dropdown which correspond to the typed text (here with a starts-with rule)
// instantiate a sortable JXList
final JXList list = new JXList(Locale.getAvailableLocales(), true);
list.setSortOrder(SortOrder.ASCENDING);
final JPopupMenu popup = new JPopupMenu();
popup.add(new JScrollPane(list));
popup.setFocusable(false);
final JTextField field = new JTextField(20);
// instantiate a PatternModel to map text --> pattern
final PatternModel model = new PatternModel();
model.setMatchRule(PatternModel.MATCH_RULE_STARTSWITH);
// listener which to update the list's RowFilter on changes to the model's pattern property
PropertyChangeListener modelListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("pattern".equals(evt.getPropertyName())) {
updateFilter((Pattern) evt.getNewValue());
}
}
private void updateFilter(Pattern newValue) {
RowFilter