我一直在尝试使用箭头键为我的应用程序的一部分。 以下我都坚持使用的键绑定的最佳实践。 我gound说,所以我采用了这样的AROW键不产生键入键事件的答案 。
然而,我的应用程序有许多组件,我发现,如果我在我的JFrame有JToolBar中的一个链接的方法不再起作用。 这是为什么?如何有一个JToolBar对象,并使用键绑定?
这里是一个SSCCE
public class ArrowTest extends JFrame {
public static void main(final String[] args){
final ArrowTest at = new ArrowTest();
at.setSize(100,200);
final JPanel jp = new JPanel();
jp.setBackground(Color.BLUE);
at.getContentPane().add(jp);
final JToolBar toolbar = new JToolBar();
toolbar.add(new JButton());
//at.add(toolbar);
at.setVisible(true);
}
public ArrowTest() {
super();
this.getContentPane().setLayout(new GridBagLayout());
this.getContentPane().setBackground(Color.BLACK);
this.setKeyBindings();
}
public void setKeyBindings() {
final int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
final ActionMap actionMap = this.getRootPane().getActionMap();
final InputMap inputMap = this.getRootPane().getInputMap(condition);
for (final Direction direction : Direction.values()) {
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V,0), direction.getText());
inputMap.put(direction.getKeyStroke(), direction.getText());
actionMap.put(direction.getText(), new MyArrowBinding(direction.getText()));
}
}
enum Direction {
UP("Up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)),
DOWN("Down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)),
LEFT("Left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)),
RIGHT("Right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));
Direction(final String text, final KeyStroke keyStroke) {
this.text = text;
this.keyStroke = keyStroke;
}
private String text;
private KeyStroke keyStroke;
public String getText() {
return text;
}
public KeyStroke getKeyStroke() {
return keyStroke;
}
@Override
public String toString() {
return text;
}
}
private class MyArrowBinding extends AbstractAction {
private static final long serialVersionUID = -6904517741228319299L;
public MyArrowBinding(final String text) {
super(text);
putValue(ACTION_COMMAND_KEY, text);
}
@Override
public void actionPerformed(final ActionEvent e) {
final String actionCommand = e.getActionCommand();
System.out.println("Key Binding: " + actionCommand);
}
}
}
默认情况下, JToolBar
注册了击键的向上/下/左/右的动作,和JToolBar
您添加到JFrame
自动抓住重点,因此结合的rootPane当你看不到任何东西(在工具栏中捕获之前发生的事件您)。
一个解决方案是使JToolBar
和JButton
不可作为焦点,让你JPanel
要成为焦点(其实你可以离开JToolBar
和JButton
,并要求重点在面板上,但是这也意味着你必须处理的重点管理你的面板):
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
public class ArrowTest extends JFrame {
public static void main(final String[] args) {
final ArrowTest at = new ArrowTest();
at.setSize(100, 200);
final JPanel jp = new JPanel();
jp.setBackground(Color.BLUE);
jp.setFocusable(true);
at.getContentPane().add(jp);
final JToolBar toolbar = new JToolBar();
JButton comp = new JButton();
toolbar.add(comp);
at.add(toolbar);
at.setVisible(true);
}
public ArrowTest() {
super();
this.getContentPane().setLayout(new GridBagLayout());
this.getContentPane().setBackground(Color.BLACK);
this.setKeyBindings();
}
public void setKeyBindings() {
for (final Direction direction : Direction.values()) {
MyArrowBinding binding = new MyArrowBinding(direction.getText());
getRootPane().registerKeyboardAction(binding, direction.getText(), direction.getKeyStroke(),
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
}
}
enum Direction {
UP("Up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)), DOWN("Down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)), LEFT("Left",
KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)), RIGHT("Right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));
Direction(final String text, final KeyStroke keyStroke) {
this.text = text;
this.keyStroke = keyStroke;
}
private String text;
private KeyStroke keyStroke;
public String getText() {
return text;
}
public KeyStroke getKeyStroke() {
return keyStroke;
}
@Override
public String toString() {
return text;
}
}
private class MyArrowBinding extends AbstractAction {
private static final long serialVersionUID = -6904517741228319299L;
public MyArrowBinding(final String text) {
super(text);
putValue(ACTION_COMMAND_KEY, text);
}
@Override
public void actionPerformed(final ActionEvent e) {
final String actionCommand = e.getActionCommand();
System.out.println("Key Binding: " + actionCommand);
}
}
}
我也取代您的通话getActionMap/getInputMap
通过一个单一的呼叫javax.swing.JComponent.registerKeyboardAction(ActionListener, String, KeyStroke, int)
继此建议答案我已经解决使用问题
public void setKeyBindings() {
final int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
final ActionMap actionMap = this.getRootPane().getActionMap();
final InputMap inputMap = this.getRootPane().getInputMap(condition);
for (final Direction direction : Direction.values()) {
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V,0), direction.getText());
inputMap.put(direction.getKeyStroke(), direction.getText());
actionMap.put(direction.getText(), new MyArrowBinding(direction.getText()));
}
condition = JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT;
actionMap = toolbar.getActionMap();
inputMap = toolbar.getInputMap(condition);
for (final Direction direction : Direction.values()) {
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V,0), direction.getText());
inputMap.put(direction.getKeyStroke(), direction.getText());
actionMap.put(direction.getText(), new MyArrowBinding(direction.getText()));
}
}