简体   繁体   English

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

[英]Editable JComboBox in Java 8 does not forward Enter key to default button

I have a editable JComboBox, with focus on this combobox, when I press Enter key, the behavior differs between Java 8 compared to older versions. 我有一个可编辑的JComboBox,专注于这个组合框,当我按下Enter键时,Java 8与旧版本之间的行为不同。

This code works as expected in Java 7 and below, but not in Java 8 (tested in Oracle JVM in Mac): 此代码在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();
            }
        });
    }
}

How do I make this code work in Java 8 and below uniformly? 如何使此代码统一在Java 8及更低版本中运行?

I found the following code in the Handler class of BasicComboBoxUI in JDK7. 我在JDK7的BasicComboBoxUIHandler类中找到了以下代码。 The Handler is added to the editor as an ActionListener: 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()));
        }
    }
}

I guess you can check the JDK8 source to see if any change has been made. 我想你可以查看JDK8源代码,看看是否有任何改动。

If changes have been made then you might need to create your own ActionListener the invokes the "enterPressed" Action of the combo box and add this Action to the editor of the combo box manually. 如果已进行更改,则可能需要创建自己的ActionListener,并调用组合框的“enterPressed”操作,并手动将此Action添加到组合框的编辑器中。

A short workaround for this 4-year-old bug: 这个4岁的bug的简短解决方法:

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 enter key event directly to the JRootPane to "call the default button binding" (whatever that is, it's not the default button in JOptionPane dialogs). 由于某种原因,BasicComboBoxUI跳过容器层次结构并将enter键事件直接传递给JRootPane以“调用默认按钮绑定”(无论如何,它不是JOptionPane对话框中的默认按钮)。 This listener manually passes the key event to the parent container. 此侦听器手动将键事件传递给父容器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM