Editable JComboBox in Java 8 does not forward "Enter" button by default

I have an editable JComboBox, with emphasis on this combo box, when I press a key Enter

, the behavior is different from Java 8 compared to older versions.

This code works as expected in Java 7 and below, but not Java 8 (tested in Oracle JVM on Mac):

package org.wiztools.comboboxdefaultbutton;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

/**
 *
 * @author subhash
 */
public class MyFrame extends JFrame {

    private static MyFrame me;

    public MyFrame() {
        Container c = getContentPane();
        c.setLayout(new BorderLayout());

        // Press Enter key with focus on this component:
        JComboBox jcb = new JComboBox(new String[]{"Option: One", "Option: Two"});
        jcb.setEditable(true);
        c.add(jcb, BorderLayout.CENTER);

        JButton jb = new JButton("Ok");
        jb.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(me, "Button pressed!");
            }
        });
        SwingUtilities.getRootPane(c).setDefaultButton(jb);
        c.add(jb, BorderLayout.EAST);

        pack();
        setVisible(true);
    }

    public static void main(String[] arg) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                me = new MyFrame();
            }
        });
    }
}

      

How do I get this code to run evenly on Java 8 and below?

+4


source to share


2 answers


I found the following code in a class Handler

BasicComboBoxUI

in JDK7. The handler is added to the editor as an ActionListener:

//
// ActionListener
//
// Fix for 4515752: Forward the Enter pressed on the
// editable combo box to the default button

// Note: This could depend on event ordering. The first ActionEvent
// from the editor may be handled by the JComboBox in which case, the
// enterPressed action will always be invoked.
public void actionPerformed(ActionEvent evt) {
    Object item = comboBox.getEditor().getItem();
    if (item != null) {
     if(!comboBox.isPopupVisible() && !item.equals(comboBox.getSelectedItem())) {
      comboBox.setSelectedItem(comboBox.getEditor().getItem());
     }
     ActionMap am = comboBox.getActionMap();
     if (am != null) {
        Action action = am.get("enterPressed");
        if (action != null) {
            action.actionPerformed(new ActionEvent(comboBox, evt.getID(),
                                   evt.getActionCommand(),
                                   evt.getModifiers()));
        }
    }
}

      



I think you can check the JDK8 source to see if any changes have been made.

If changes have been made, you may need to create your own ActionListener that invokes the "enterPressed" action on the combo box and adds this action to the combo box editor manually.

+2


source


Short solution to this 4 year old error:

comboBox.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
    @Override
    public void keyPressed(KeyEvent e) {
        if (!comboBox.isPopupVisible() && e != null && e.getKeyCode() == KeyEvent.VK_ENTER) {
            Container parent = comboBox.getParent();
            if (parent != null) parent.dispatchEvent(e);
        }
    }
});

      



For some reason, BasicComboBoxUI skips the container hierarchy and passes the key entry event directly to the JRootPane to "trigger the default button binding" (whatever it is, it's not the default button in JOptionPane dialogs). This listener manually dispatches the key event to the parent container.

0


source







All Articles