将 JTextField 添加到 JMenuBar 会取消 KeyListener 响应!! - 怎么修?
Adding JTextField to JMenuBar cancels KeyListener responses!! - How to fix?
以下是SSCCE代码;它工作正常并且 KeyListener
正确响应,但是向 JMenuBar
添加 JTextField
会导致 KeyListener
根本不响应。
转到 uncomment/comment 添加 JTextField
的行以查看差异:menuBar.add(textField);
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class JMenueWithKeyListenerExample extends JPanel {
JTextField textField;
JMenuBar menuBar;
JFrame f;
public JMenueWithKeyListenerExample() {
textField = new JTextField();
menuBar = new JMenuBar();
JMenu fileMenue = new JMenu("File");
JMenuItem menuItem1 = new JMenuItem("Item 1");
JMenuItem menuItem2 = new JMenuItem("Item 2");
fileMenue.add(menuItem1);
fileMenue.add(menuItem2);
menuBar.add(fileMenue);
//menuBar.add(textField); // switch between comment & uncomment to see the difference
f = new JFrame();
f.setJMenuBar(menuBar);
f.add(this);
f.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if ((e.getKeyCode() == KeyEvent.VK_Z) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
System.out.println("undo");
}
}
});
f.setSize(400, 400);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JMenueWithKeyListenerExample();
}
});
}
}
添加快捷键的首选方法是使用input map and action map,像这样:
f.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_DOWN_MASK),
"Undo");
f.getRootPane().getActionMap()
.put("Undo", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("undo");
}
});
当然,在实际代码中你应该定义一个常量而不是直接硬编码 "Undo"
动作名称。也许单独定义操作,给它一个合适的名称和其他有用的属性。
以下是SSCCE代码;它工作正常并且 KeyListener
正确响应,但是向 JMenuBar
添加 JTextField
会导致 KeyListener
根本不响应。
转到 uncomment/comment 添加 JTextField
的行以查看差异:menuBar.add(textField);
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class JMenueWithKeyListenerExample extends JPanel {
JTextField textField;
JMenuBar menuBar;
JFrame f;
public JMenueWithKeyListenerExample() {
textField = new JTextField();
menuBar = new JMenuBar();
JMenu fileMenue = new JMenu("File");
JMenuItem menuItem1 = new JMenuItem("Item 1");
JMenuItem menuItem2 = new JMenuItem("Item 2");
fileMenue.add(menuItem1);
fileMenue.add(menuItem2);
menuBar.add(fileMenue);
//menuBar.add(textField); // switch between comment & uncomment to see the difference
f = new JFrame();
f.setJMenuBar(menuBar);
f.add(this);
f.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if ((e.getKeyCode() == KeyEvent.VK_Z) && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
System.out.println("undo");
}
}
});
f.setSize(400, 400);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JMenueWithKeyListenerExample();
}
});
}
}
添加快捷键的首选方法是使用input map and action map,像这样:
f.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_DOWN_MASK),
"Undo");
f.getRootPane().getActionMap()
.put("Undo", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("undo");
}
});
当然,在实际代码中你应该定义一个常量而不是直接硬编码 "Undo"
动作名称。也许单独定义操作,给它一个合适的名称和其他有用的属性。