我目前正在测试KeyEventDispatcher
。
因此,我写了一个小JFrame
来实现KeyEventDispatcher
和我自己的 keyPressed
和keyReleased
方法。
在这些方法中,我使用基于标志的系统来仅检测每个箭头键的第一次按键。
如果您单独单击键,一切正常。但是,如果您单击"向右"、"向上"、"向左"(不释放其中任何一个(,则无法识别 Left 键。
控制台输出:
右键点击
四 向上点击
6
预期产出:
右键点击
四 向上点击
6 左键点击
7
我的代码如下:
主类:
public class Main {
public static void main(String[] args) {
UI m = new UI();
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(m);
}
}
用户界面类:
public class UI extends JFrame implements KeyEventDispatcher{
short lurd = 0;
enum KEYSTATES{
LEFT(1),
UP(2),
RIGHT(4),
DOWN(8);
private int m_val;
KEYSTATES(int val){
m_val = val;
}
public int getm_val(){
return m_val;
}
}
public UI(){
setSize(800,600);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
switch(e.getID())
{
case KeyEvent.KEY_PRESSED:
keyPressed(e);
return true;
case KeyEvent.KEY_RELEASED:
keyReleased(e);
return true;
}
return false;
}
private void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT && ((lurd & KEYSTATES.LEFT.getm_val()) != KEYSTATES.LEFT.getm_val())){
lurd |= KEYSTATES.LEFT.getm_val();
System.out.println("Left clicked");
System.out.println(lurd);
}
else if(e.getKeyCode() == KeyEvent.VK_UP && ((lurd & KEYSTATES.UP.getm_val()) != KEYSTATES.UP.getm_val()))
{
lurd |= KEYSTATES.UP.getm_val();
System.out.println("Up clicked");
System.out.println(lurd);
}
else if(e.getKeyCode() == KeyEvent.VK_RIGHT && ((lurd & KEYSTATES.RIGHT.getm_val()) != KEYSTATES.RIGHT.getm_val()))
{
lurd |= KEYSTATES.RIGHT.getm_val();
System.out.println("Right clicked");
System.out.println(lurd);
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN && ((lurd & KEYSTATES.DOWN.getm_val()) != KEYSTATES.DOWN.getm_val()))
{
lurd |= KEYSTATES.DOWN.getm_val();
System.out.println("Down clicked");
System.out.println(lurd);
}
}
private void keyReleased(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT && ((lurd & KEYSTATES.LEFT.getm_val()) == KEYSTATES.LEFT.getm_val())){
lurd &= ~KEYSTATES.LEFT.getm_val();
System.out.println("Left released");
System.out.println(lurd);
}
else if(e.getKeyCode() == KeyEvent.VK_UP && ((lurd & KEYSTATES.UP.getm_val()) == KEYSTATES.UP.getm_val()))
{
lurd &= ~KEYSTATES.UP.getm_val();
System.out.println("Up released");
System.out.println(lurd);
}
else if(e.getKeyCode() == KeyEvent.VK_RIGHT && ((lurd & KEYSTATES.RIGHT.getm_val()) == KEYSTATES.RIGHT.getm_val()))
{
int x = ~KEYSTATES.RIGHT.getm_val();
lurd &= x;
System.out.println("Right released");
System.out.println(lurd);
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN && ((lurd & KEYSTATES.DOWN.getm_val()) == KEYSTATES.DOWN.getm_val()))
{
lurd &= ~KEYSTATES.DOWN.getm_val();
System.out.println("Down released");
System.out.println(lurd);
}
}
}
要解决此问题,请在pressed
时为特定keys
保留boolean
变量的引用,并使它们true
,并在released
它们各自的key
时使这些变量false
。
下面是一个示例:
这是keyPressed()
方法:
public void keyPressed(KeyEvent e)
{
switch(e.getKeyCode())
{
case VK_LEFT: setLeftKeyPressed(true);
break;
case VK_RIGHT: setRightKeyPressed(true);
break;
case VK_UP: setUpKeyPressed(true);
break;
case VK_DOWN: setDownKeyPressed(true);
break;
//...
}
printKeyStates();
}
这是keyReleased()
方法:
public void keyReleased(KeyEvent e)
{
switch(e.getKeyCode())
{
case VK_LEFT: setLeftKeyPressed(false);
break;
case VK_RIGHT: setRightKeyPressed(false);
break;
case VK_UP: setUpKeyPressed(false);
break;
case VK_DOWN: setDownKeyPressed(false);
break;
//...
}
printKeyStates();
}
这是printKeyStates()
方法的样子:
public void printKeyStates()
{
print("Left", isLeftKeyPressed());
print("Right", isRightKeyPressed());
print("Up", isUpKeyPressed());
print("Down", isDownKeyPressed());
}
private void print(String key, boolean isPressed)
{
System.out.println(key + " key is " + (isPressed ? "" : "NOT ") + "pressed.");
}
boolean
变量如下所示:
private boolean isLeftKeyPressed;
private boolean isRightKeyPressed;
private boolean isUpKeyPressed;
private boolean isDownKeyPressed;
他们的setters
像:
public void setLeftKeyPressed(boolean value)
{
isLeftKeyPressed = value;
}
同样,其他二传手
...getters
像:
public boolean isLeftKeyPressed()
{
return isLeftKeyPressed;
}
同样,其余的获得者...
通常,在游戏和预期这种行为的网络遥控器中,可以通过这种技术来解决。
boolean
变量flips
的差异将让您知道任何key
发生的"点击"计数。要记录该"点击"计数,您可以使用计数变量来保存任何键发生的点击次数的状态。
以下是您可以做到这一点的方法:
int leftKeyClickCount = 0; // Initially ZERO
然后,在setter
isLeftKeyPressed
变量时,您可以执行以下操作:
public void setLeftKeyPressed(boolean value)
{
if(isLeftKeyPressed != value)
{
isLeftKeyPressed = value;
++leftKeyClickCount;
}
}
同样,其他二传手也可以写...
然后,您可以通过打印适当的xyzKeyClickCount
变量值来打印每个键的点击次数,例如:
System.out.println("Left key clicked: " + leftKeyClickCount + " time(s).");