метод JComboBox.isTableCellEditor
работает для перемещения стрелок по списку, но не работает для опережающего ввода, поддерживаемого KeySelectionManager.т. е. вы все еще получаете ActionEvents для каждой не навигационной клавиши, которую вводит пользователь, поскольку JComboBox интерпретирует эти символы для поиска, хотя модель перемещается (или приближается) к выбранному пользователем выбору.
это решение имеетнедостаток в том, что он изменяет команду действия для щелчков мыши, что было для меня компромиссом ОК, потому что поток графического интерфейса вынуждает пользователя менять фокус вдали от поля со списком
Я закончил тем, что сделал специальныйKeyListener, который полагается на изменение команды действия по умолчанию поля со списком с comboBoxChanged
на comboBoxMovement
.Вот строка кода, которая мне нужна после инициализации моего поля со списком:
setExplicitSelectionManager(myComboBox);
... а вот метод и содержащийся в нем класс, которые выполняют всю работу:
private void setExplicitSelectionManager(JComboBox comboBox) {
class ExplicitSelectionManager implements KeyListener, FocusListener {
private JComboBox src;
private KeyListener superKeyListener;
ExplicitSelectionManager(JComboBox src) {
this.src = src;
// we like what the default key listener does, but not the action command
// it uses for ActionEvents it fires for plain text type-ahead characters
this.superKeyListener = src.getKeyListeners()[0]; // we only have one
src.removeKeyListener(superKeyListener); // will be replace right away, below
}
@Override
public void keyTyped(KeyEvent e) {
// basic combo box has no code in keyTyped
}
@Override
public void keyPressed(KeyEvent e) {
// in the default JComboBox implementation, the KeySelectionManager is
// called from keyPressed. I'm fine with the implementation of
// the default, but I don't want it firing ActionEvents that will cause
// model updates
src.setActionCommand("comboBoxMovement");
this.superKeyListener.keyPressed(e);
src.setActionCommand("comboBoxChanged");
if (e.getKeyCode() == 10) {
src.setSelectedIndex(src.getSelectedIndex());
}
}
@Override
public void keyReleased(KeyEvent e) {
// basic combo box has no code in keyReleased
}
@Override
public void focusGained(FocusEvent e) {
}
@Override
// this will also give us the event we want, if the user decides to Tab out of
// the combo box, instead of hitting Enter
public void focusLost(FocusEvent e) {
src.setSelectedIndex(src.getSelectedIndex());
}
}
ExplicitSelectionManager newSelectionManager = new ExplicitSelectionManager(comboBox);
comboBox.addKeyListener(newSelectionManager);
comboBox.addFocusListener(newSelectionManager);
}
... а вот и действие, выполненное методом
private void comboBoxActionPerformed(java.awt.event.ActionEvent evt) {
JComboBox source = (JComboBox) evt.getSource();
// "comboBoxChanged" is the default,
// so any normal JComboBox can also use this action listener
if (evt.getActionCommand().equals("comboBoxChanged")) {
updateModel(source.getName(), (String) source.getSelectedItem());
}
}