【发布时间】:2015-02-26 14:45:48
【问题描述】:
我需要使用 JButtons 和键盘发送导航命令。如果按下“向上”按钮/向上键,我需要发送“向北移动”命令,如果按下向上和向左按钮(从键盘),我需要发送“向北移动”命令等。命令应该是定期发送(每 1 秒)。以下是我的代码。
为了解释更多,
视图上有三个 JButton。我们称它们为 jUp、jLeft 和 jRight。当用户按下视图上的 jUp 按钮时,程序应该定期发送 moveNorth 命令,直到用户释放 jUp 按钮。当用户按下键盘上的向上按钮时,应该会发生同样的事情,并且 jUp 按钮应该看起来被按下,直到用户释放键盘向上按钮。当用户同时按下键盘的向上和向左按钮时,jUp 和 jLeft 按钮应显示为按下状态,直到用户松开键盘按钮。在用户释放键盘按钮之前,应该定期发送 move northWest 命令。在代码中,我刚刚使用 System.out.println 打印了命令。
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
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.KeyStroke;
import javax.swing.Timer;
public class ButtonDemo {
private JPanel buttons;
private Timer t;
private JButton upButton;
private JButton leftButton;
private JButton rightButton;
public static void main(String[] args) {
new ButtonDemo().run();
}
public ButtonDemo() {
buttons = new JPanel(new BorderLayout());
this.t = new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (upButton.isSelected() && leftButton.isSelected()) {
System.out.println("Move north west");
} else if (upButton.isSelected() && rightButton.isSelected()) {
System.out.println("Move north east");
} else if (upButton.isSelected()) {
System.out.println("Move north");
} else {
t.stop();
}
}
});
}
void run() {
this.upButton = new JButton("Up");
buttons.add(upButton, BorderLayout.NORTH);
setupButton(upButton, "Up", KeyEvent.VK_UP);
this.leftButton = new JButton("Left");
buttons.add(leftButton, BorderLayout.WEST);
setupButton(leftButton, "Left", KeyEvent.VK_LEFT);
this.rightButton = new JButton("Right");
buttons.add(rightButton, BorderLayout.EAST);
setupButton(rightButton, "Right", KeyEvent.VK_RIGHT);
JFrame frame = new JFrame("FrameDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(buttons, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
private void setupButton(JButton button, String key, int vkUp) {
buttons.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(vkUp, 0),
key + " pressed");
buttons.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(vkUp, 0, true),
key + " released");
buttons.getActionMap().put(key + " pressed", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
button.setSelected(true);
pressed(key);
}
});
buttons.getActionMap().put(key + " released", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
button.setSelected(false);
}
});
}
private void pressed(String key) {
if (!t.isRunning()) {
t.start();
}
}
}
现在回答问题。
a) 即使我调用了 setSelected 方法,按钮状态也不会变为按下状态。 (视觉上它不会变为按下状态)。我怎样才能做到这一点?
b) 是否有更好/更标准的方式来实现此功能?使用助记符/ExecutorService 等..?我将动作添加到“按钮”元素的输入映射中是否正确。 ( buttons.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)正确吗?)面板会在选项卡中,并且选择该选项卡时应使用。
【问题讨论】:
-
你是否关心按下的顺序(即如果我向上按,然后向左,然后向左松开,你是否关心首先向上的事实)?
-
顺序无关紧要。应该根据现在按下的按钮发送消息。由于问题中的代码现在适用于键盘按钮。根据现在按下的键盘按钮,UI 按钮应该看起来被按下。
标签: java swing key-bindings