带有KeyEventDispatcher的JFrame无法单击3个箭头键



我目前正在测试KeyEventDispatcher

因此,我写了一个小JFrame来实现KeyEventDispatcher和我自己的 keyPressedkeyReleased方法。

在这些方法中,我使用基于标志的系统来仅检测每个箭头键的第一次按键。

如果您单独单击键,一切正常。但是,如果您单击"向右"、"向上"、"向左"(不释放其中任何一个(,则无法识别 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).");

相关内容

  • 没有找到相关文章

最新更新