Как сделать, чтобы выбранный элемент JComboBox не изменялся при прокрутке его всплывающего списка с помощью клавиатуры - PullRequest
12 голосов
/ 04 марта 2011

У меня есть компонент JComboBox на панели и ItemListener, прикрепленный к нему. Но он срабатывает после каждого нажатия клавиш вверх / вниз (при прокрутке через открытый всплывающий список). Я хочу изменить выбранное значение после того, как пользователь подтвердит выбор нажатием, например, клавиши Enter.

Это не тот случай, когда используется мышь. Когда я перемещаю мышь по списку в выпадающем списке, выделение следует за указателем мыши, но выбранный элемент не изменяется, пока я не нажму кнопку мыши. Я хотел бы иметь такое же поведение для клавиатуры, т. Е. Перемещение выделения с помощью стрелок вверх / вниз не изменяет выбранный элемент, но нажатие клавиши Enter приводит к изменениям.

Ответы [ 4 ]

19 голосов
/ 04 марта 2011

Я считаю, что вы должны быть в состоянии:

comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);

после того, как вы создали comboBox экземпляр для , получите эту функцию

2 голосов
/ 10 ноября 2016

В Java 8 они исправили это поведение, но срабатывали, только если вы установили одно свойство пользовательского интерфейса

UIManager.getLookAndFeelDefaults().put("ComboBox.noActionOnKeyNavigation", true);
1 голос
/ 24 мая 2013

метод 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());
    }
}                                               
0 голосов
/ 04 марта 2011

Это ожидаемое поведение с ItemListener. всякий раз, когда отображаемое значение изменяется, происходит событие. Для вашего требования используйте ActionListener.

...