[英]java swing key bindings - missing action for released key
注册了“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);
}
});
}
}
更新 :这是在释放空间之前意外点击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);
}
});
}
}
有意义的是,当Control键仍然按下时,不会触发released SPACE
事件。 我希望control released SPACE
事件被解雇。
将以下内容添加到您的代码中:
getInputMap().put(KeyStroke.getKeyStroke("control released SPACE"), "released");
出于同样的原因,如果您先按住Control键, SPACE
事件将不会触发。 因此,您还需要为control SPACE
添加绑定。
您需要对所有修改键执行此操作,这可能是也可能不是跟踪关键事件的简单解决方案。
您的操作系统可能不会触发keyReleased
事件,而只会keyTyped
keyPressed
和keyTyped
事件或其他组合,因此请先检查该事件。 您可能只需要检查keyTyped
事件而不是keyReleased
,您将完成它。
简短回答:
使用位掩码或数组来跟踪当前处于“已按下”状态的键,然后使用那些值来触发事件。 也就是说,不要直接使用Swing事件来触发应用程序中的响应 - 您需要一个基本上存储键盘状态的额外层,并从该状态开始执行相关操作。
还有一些方法可用( 参见本教程结尾 - “isAltDown”,“isCtrlDown”等 )来检查当您收到按下“Space”键之类的事件时是否按下了修改键。
答案很长:
你按下并释放按键时会触发事件是正确的。 它必须以这种方式工作,以便您可以支持应该单独处理这些事件的应用程序,而不是一起处理。 一个例子(虽然这不是唯一一个)是PC上的视频游戏,你可能会同时按下多个字母/修改键(例如, A
向左移动, W
向前移动)游戏必须对待这两个事件作为不同的输入,而不是复合输入,导致你的前进 - 左移动。
所以,你基本上想做的事情,如果你需要处理复合输入,就有一个简单的应用程序需要响应的动作数组,以及它们相关的键绑定(无论是单键还是多键都不重要) )。 当按下某个键时,你基本上会打开该键的标志,表示它当前处于“按下”状态,并在释放时清除该标志。
然后,要触发您的事件,您只需检查所有按下的键(通过检查哪些键“标志”处于活动状态),如果按下特定事件的键组合,则触发事件。
如果你有少于32个触发事件的键,那么你实际上可以使用位掩码和32位int
值,而不是数组。 事实上,如果可以的话,这样做会简单得多。 如果您需要多达64个密钥,请使用long
执行相同的操作。 如果您触发事件的键很少(例如8或更少),则可以使用8位short
类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.