有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java处理多次按键忽略重复按键

我在另一个问题(>;How do I handle simultaneous key presses in Java?)的评论部分提出了这个问题,并被要求提出一个新问题

我的问题是,当我创建按键的ArrayList时,如果用户按住按键,则无法通过keyReleased事件快速删除按键。我希望运动与“asdf”和北,东,南,西,东北。。。等等

以下是这两个事件的代码:

@Override
public void keyPressed(KeyEvent e) {
    if(chatTextField.isFocusOwner() == true){
        //do nothing - don't walk
    } else {
        logger.debug("Key Pressed: " + e.getKeyChar());
        lastKey = keysPressed.get(keysPressed.size()-1);

        for (String key : keysPressed){
            if (!key.contains(String.valueOf(e.getKeyChar())) && !lastKey.contains(String.valueOf(e.getKeyChar()))){
                keysPressed.add(String.valueOf(e.getKeyChar()));
                System.out.println("ADDED: " + keysPressed);
            }
        }

        String keysList = keysPressed.toString();
        if (keysList.contains("w")){
            if (keysList.contains("d")){
                requestCharacterMove("NorthEast");
            } else if(keysList.contains("a")){
                requestCharacterMove("NorthWest");
            } else{
                requestCharacterMove("North");
            }
        } else if (keysList.contains("s")){
            if (keysList.contains("d")){
                requestCharacterMove("SouthEast");
            } else if(keysList.contains("a")){
                requestCharacterMove("SouthWest");
            } else{
                requestCharacterMove("South");
            }
        } else if (keysList.contains("d")){
            requestCharacterMove("East");
        } else if (keysList.contains("a")){
            requestCharacterMove("West");
        }
    }
}

@Override
public void keyReleased(KeyEvent e) {
    if(chatTextField.isFocusOwner() == true){
        //do nothing - don't walk
    } else {
        logger.debug("Key Released: " + e.getKeyChar());
        for (String key : keysPressed){
            if (key.contains(String.valueOf(e.getKeyChar()))){
                keysPressed.remove(String.valueOf(e.getKeyChar()));
                System.out.println("REMOVED: " + keysPressed);
            }
        }
    }
}

@Override
public void keyTyped(KeyEvent arg0) {
    // TODO Auto-generated method stub

}

在我通过lastKey(String)变量添加第二个签入之前,创建的金字塔是巨大的。即使是第二次检查,列表也会增加,并且几乎总是有两个或三个重复项。这方面的任何帮助都将是巨大的,因为我的角色移动笨拙(

另外,任何删除到char、string、arrayList的重复转换的方法都会很好,因为我担心我在“简单”的东西上使用了太多的类型


共 (3) 个答案

  1. # 1 楼答案

    作为替代方案,这个game使用数字键盘来实现每个(半)基本方向,只需一次按键。默认排列显示在设计部分。这些键可以单独重新分配,以便在键盘上的任何位置映射类似的玫瑰花结

  2. # 2 楼答案

    看起来您没有正确处理Java中的线程。任何Java程序至少有三个线程。它们是主程序线程,事件调度线程,还有一个我现在不记得了

    每当你收到一个事件,它都会通过一个特殊的线程传递给你(我相信这是事件调度线程,但这不是重点)。您不允许在此线程上执行任何(需要时间的)操作,这将冻结您的输入并导致您错过事件,使Java看起来没有响应。所以发生的事情是你打破了java中的事件系统。您应该做的是将结果存储在某种缓冲区中,这是您可以期望对事件执行的最快的操作,然后,正如我将描述的那样,它将在稍后处理

    [旁白: 一个有趣的应用程序是制作一个简单的gui,按下按钮调用,在线程上等待大约5秒钟。整个gui将冻结,直到延迟完成!]

    你应该有一个不同的线程在旁边运行(可能是你的主线程)。它将运行某种循环,控制程序中的帧,每个游戏周期完成一次。每个循环一次,该线程读取存储在输入缓冲区中的结果并进行处理。这背后的理论很简单,但执行过程可能有点混乱,因为您需要确保不会删除或多次读取输入事件。不管怎样,祝你的比赛好运

  3. # 3 楼答案

    你观察到事情处理得很慢很可能是由许多系统造成的。出来println()语句

    你的问题是,你没有得到对角线移动源于你有点错误的检查逻辑-而不是显式地检查(例如)键AB是否被按下,只需单独检查它们-键A将字符移动到一个方向,B移动到另一个方向。总的来说(例如),通过向西向北移动,你将有效地向西北移动

    您可以使用java,而不是一系列按下的键。util。位设置,只需为当前按下的每个键设置位。这也将大大减少您需要编写的代码量(按键只设置按键代码指示的位,按键释放则清除)。要检查是否按下了键,请询问位集,然后查看代码位当前是否已设置

    编辑:使用位集而不是列表的示例

    public class BitKeys implements KeyListener {
    
        private BitSet keyBits = new BitSet(256);
    
        @Override
        public void keyPressed(final KeyEvent event) {
            int keyCode = event.getKeyCode();
            keyBits.set(keyCode);
        }
    
        @Override
        public void keyReleased(final KeyEvent event) {
            int keyCode = event.getKeyCode();
            keyBits.clear(keyCode);
        }
    
        @Override
        public void keyTyped(final KeyEvent event) {
            // don't care
        }
    
        public boolean isKeyPressed(final int keyCode) {
            return keyBits.get(keyCode);
        }
    
    }
    

    我让这个例子实现了KeyListener,所以你甚至可以按原样使用它。当你需要知道某个键是否按下时,只需使用isKeyPressed()。你需要决定是喜欢使用原始密钥代码(就像我做的那样)还是使用密钥字符(就像你现在做的那样)。在任何情况下,您都可以看到使用BitSet类记录密钥的代码量如何减少到几行:)