注册了“SPACE”和“已发布SPACE”的键绑定,当空格是唯一按下/释放的键时,按照广告的方式工作,我注意到按下空格,然后按ctrl(或任何其他修改键),然后释放空间最后释放ctrl将导致执行与“SPACE”相关联的操作,但不会执行与“释放的SPACE”相关联的操作。
一旦不再按空格(或同时按下修改键),导致动作执行的首选方法是什么?我只在Windows 7,64位上尝试过这个。
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.AbstractAction;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import java.awt.Cursor;
class Bind extends JPanel {
{
getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed");
getInputMap().put(KeyStroke.getKeyStroke("released SPACE"), "released");
getActionMap().put("pressed", new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
System.out.println("pressed");
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
}
});
getActionMap().put("released", new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
System.out.println("released");
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
JFrame f = new JFrame("Key Bindings");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Bind());
f.setSize(640, 480);
f.setVisible(true);
}
});
}
}
UPDATE :这是在释放空间之前意外点击ctrl,alt或shift时避免粘滞空间的方法:
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.AbstractAction;
import javax.swing.KeyStroke;
import java.awt.event.ActionEvent;
import java.awt.Cursor;
class Bind extends JPanel {
{
getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "pressed");
getInputMap().put(KeyStroke.getKeyStroke("released SPACE"), "released");
getInputMap().put(KeyStroke.getKeyStroke("ctrl released SPACE"), "released");
getInputMap().put(KeyStroke.getKeyStroke("shift released SPACE"), "released");
getInputMap().put(KeyStroke.getKeyStroke("shift ctrl released SPACE"), "released");
getInputMap().put(KeyStroke.getKeyStroke("alt released SPACE"), "released");
getInputMap().put(KeyStroke.getKeyStroke("alt ctrl released SPACE"), "released");
getInputMap().put(KeyStroke.getKeyStroke("alt shift released SPACE"), "released");
getInputMap().put(KeyStroke.getKeyStroke("alt shift ctrl released SPACE"), "released");
getActionMap().put("pressed", new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
System.out.println("pressed");
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
}
});
getActionMap().put("released", new AbstractAction() {
@Override public void actionPerformed(ActionEvent e) {
System.out.println("released");
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
JFrame f = new JFrame("Key Bindings");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new Bind());
f.setSize(640, 480);
f.setVisible(true);
}
});
}
}
答案 0 :(得分:7)
有意义的是,当仍然按住Control键时,不会触发released SPACE
事件。我希望能解雇control released SPACE
事件。
将以下内容添加到您的代码中:
getInputMap().put(KeyStroke.getKeyStroke("control released SPACE"), "released");
出于同样的原因,如果您先按住Control键,SPACE
事件将不会触发。因此,您还需要为control SPACE
添加绑定。
您需要对所有修改键执行此操作,这可能是也可能不是跟踪关键事件的简单解决方案。
答案 1 :(得分:4)
您的操作系统可能不会触发keyReleased
个事件,而只会触发keyPressed
和keyTyped
个事件或其他组合,因此请先检查一下。您可能只需要检查keyTyped
个事件而不是keyReleased
,您就可以完成它了。
简答:
使用bitmask或数组来跟踪当前处于“已按下”状态的键,然后使用那些值来触发事件。也就是说,不要直接使用Swing事件来触发应用程序中的响应 - 您需要一个基本上存储键盘状态的额外层,并从该状态开始执行相关操作。
当您收到按下“Space”键之类的事件时,还有一些方法(see the end of this tutorial - "isAltDown", "isCtrlDown" etc.)可以检查是否按下了修改键。
答案很长:
当按下并释放按键时,事件会被触发,这是正确的。它必须以这种方式工作,以便您可以支持应该单独处理这些事件的应用程序,而不是一起处理。一个例子(虽然这不是唯一的例子)是PC上的视频游戏,你可能会同时按下多个字母/修饰键(例如,A
向左移动,W
去前进)并且游戏必须将这两个事件视为不同的输入,而不是复合输入,从而导致你的前进左右移动。
所以,你基本上想做的事情,如果你需要处理复合输入,就有一个简单的应用程序需要响应的动作数组,以及它们相关的键绑定(无论是单键还是多键都没有'真的很重要)。当按下某个键时,你基本上会打开该键的标志,表示它当前处于“按下”状态,并在释放时清除该标志。
然后,要触发您的事件,您只需检查所有按下的键(通过检查哪些键“标志”处于活动状态),如果按下特定事件的键组合,则触发该事件。
如果您触发事件的键少于32个,那么您实际上可以使用bitmask和32位int
值而不是数组执行此操作。事实上,如果可以的话,这样做会简单得多。如果您需要最多64个密钥,请使用long
执行相同的操作。如果您触发事件的键很少(例如8个或更少),则可以使用8位short
类型。