我有一个可编辑的JComboBox,重点放在这个组合框上,当我按Enter
键时,与旧版本相比,Java8的行为有所不同。
此代码在Java7及以下版本中按预期工作,但在Java8(在Oracle中测试JVM在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();
}
});
}
}
如何让这段代码在Java8及以下统一工作?
我在JDK7的BasicComboBoxUI
的Handler
类中找到了以下代码。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,调用组合框的“尽管如此”操作,并手动将此操作添加到组合框的编辑器中。
这个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);
}
}
});
由于某种原因,BasicComboBoxUI跳过了容器层次结构,并将enter键事件直接传递给JRootPane以“调用默认按钮绑定”(无论是什么,它都不是JOptionPane对话框中的默认按钮)。此侦听器手动将键事件传递给父容器。