Java 8中的可编辑JComboBox不会将Enter键转发到默认按钮

时间:2014-10-06 13:18:06

标签: java swing java-8 jcombobox

我有一个可编辑的JComboBox,专注于这个组合框,当我按Enter键时,Java 8与旧版本的行为不同。

此代码在Java 7及更低版本中按预期工作,但在Java 8中不起作用(在Mac中的Oracle JVM中测试):

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

如何使此代码统一在Java 8及更低版本中运行?

2 个答案:

答案 0 :(得分:2)

我在JDK7的HandlerBasicComboBoxUI中找到了以下代码。 Handler作为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()));
        }
    }
}

我猜您可以查看JDK8源代码,看看是否有任何更改。

如果已经进行了更改,那么您可能需要创建自己的ActionListener,并调用" enterPressed"组合框的操作,并手动将此Action添加到组合框的编辑器中。

答案 1 :(得分:0)

此已有4年历史的错误的简短解决方法:

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

由于某种原因,BasicComboBoxUI跳过了容器层次结构,并将enter键事件直接传递给JRootPane以“调用默认按钮绑定”(无论如何,它不是JOptionPane对话框中的默认按钮)。该侦听器手动将key事件传递给父容器。