Ответ 1
Я считаю, что вы должны это сделать:
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
после того, как вы создали экземпляр comboBox
для получить эту функциональность
У меня есть компонент JComboBox на панели и ItemListener, прикрепленный к нему. Но он запускается после каждого нажатия клавиши вверх/вниз (при прокрутке, хотя открыт всплывающий список). Я хочу изменить выбранное значение после того, как пользователь примет выбор, нажав, например, клавишу Enter.
Это не относится к использованию мыши. Когда я перемещаю мышь над списком combobox, подсветка следует указателю мыши, но выбранный элемент не изменяется до тех пор, пока я не нажму кнопку мыши. Я хотел бы иметь такое же поведение для клавиатуры, т.е. Перемещение выделения с помощью стрелки вверх/вниз не изменяет выбранный элемент, но нажатие Enter делает.
Я считаю, что вы должны это сделать:
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
после того, как вы создали экземпляр comboBox
для получить эту функциональность
Метод JComboBox.isTableCellEditor
работает для перемещения по стрелке через список, но не работает для ввода типа, поддерживаемого KeySelectionManager. то есть вы все равно получаете ActionEvents для каждого неавигационного ключа, который пользователь вводит, поскольку JComboBox интерпретирует эти символы для поиска, хотя модель перемещается (или приближается к) для выбора пользователя.
это решение имеет недостаток в том, что он изменяет команду действий для щелчков мыши, что для меня было компромиссом OK, потому что поток GUI заставляет пользователя изменять фокус в поле со списком
В итоге я создал специальный 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());
}
}
В Java 8 они исправили это поведение, но только триггер, если u установил одно свойство пользовательского интерфейса
UIManager.getLookAndFeelDefaults().put("ComboBox.noActionOnKeyNavigation", true);
Его ожидаемое поведение с ItemListener
. всякий раз, когда отображаемое значение меняет событие. Для вашего требования используйте ActionListener
.