开发者

How to make JComboBox selected item not changed when scrolling through its popuplist using keyboard

I have a JComboBox component in the panel and ItemListener attached to it. But it gets fired after every up/down keypress (when scrolling though opened popup list). I want to change the selected value after the user accepts selection by pressing for example Enter key.

This is not a case when using mouse. When I move mouse over the combobox's list the h开发者_如何学Pythonighlight follows mouse pointer, but selected item is not changed until I press the mouse button. I would like to have the same behavior for keyboard, i.e. moving highlight via up/down arrow does not change selected item, but pressing Enter does.


I believe you should be able to do:

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

after you have created your comboBox instance to get this functionality


In Java 8 they have fixed this behaviour, but only trigger if u set one UI property

UIManager.getLookAndFeelDefaults().put("ComboBox.noActionOnKeyNavigation", true);


the JComboBox.isTableCellEditor method works for arrow movement through the list, but does not work for type-ahead supported by the KeySelectionManager. i.e. you still get ActionEvents for every non-navigation key the user types, as the JComboBox interprets those characters for searching though the model to move to (or move close to) the user's intended selection.

this solution has a drawback in that it changes the action command for mouse clicks, which was a OK compromise for me because the the flow of the GUI forces the user to change the focus away from the combo box

I ended up making a special KeyListener, that relys on changing the combo box's default action command from comboBoxChanged to comboBoxMovement. Here's the line of code I need after my combo box is all initialized:

setExplicitSelectionManager(myComboBox);

... and here is the method and its contained class that do all the work:

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);

}

... and here's the action performed method

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());
    }
}                                               


Its the expected behavior with the ItemListener. whenever the displayed value changes the event is fired. For your requirement use an ActionListener.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜