如何在Java中处理同时按下的键?

19

如何在Java中处理同时按下的按键?

我正在尝试编写一个游戏,并需要同时处理多个按键。

当我按住一个键(比如向前移动),然后再按下另一个键(例如向左转),新的按键被检测到,但旧的按键不再被检测到。

4个回答

21

一种方法是自己跟踪当前按下的键。

当您收到 keyPressed 事件时,将新键添加到列表中;当您收到 keyReleased 事件时,从列表中删除该键。

然后在游戏循环中,可以根据键列表执行操作。


那似乎不是很hackish。 (显然与焦点有关的问题略微存在 - 我猜假设所有的焦点都在增益/失去焦点上。) - Tom Hawtin - tackline
@MichaelMyers 你如何处理按键重复的情况?如果我按住一个键,它会像一个侧面的金字塔一样:a | a, a | a, a, a| a, a, a, a| a, a, a| a, a | a。 - KisnardOnline
@JayAvon:我认为这值得提出一个新问题。 - Michael Myers
@MichaelMyers 这是新的问题链接:http://stackoverflow.com/questions/11851155/handle-multiple-key-presses-ignoring-repeated-key。任何帮助都将不可思议。 - KisnardOnline
我建议使用BitSet而不是键列表。 - Radu Simionescu
这正是我寻找的答案 - 我正在使用 JOGL,在按键时将 flat 设置为 true,在释放时将其设置为 false。太棒了,谢谢! - Savara

4
以下是一个代码示例,演示如何在按下CTRL+Z时执行某个操作:
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
class p4 extends Frame implements KeyListener
{
    int i=17;
    int j=90;
    boolean s1=false;
    boolean s2=false;

    public p4()
    {
        Frame f=new Frame("Pad");

        f.setSize(400,400);
        f.setLayout(null);
        Label l=new Label();
        l.setBounds(34,34,88,88);
        f.add(l);

        f.setVisible(true);
        f.addKeyListener(this);
    }

    public static void main(String arg[]){
        new p4();
    }

    public void keyReleased(KeyEvent e) {
        //System.out.println("re"+e.getKeyChar());

        if(i==e.getKeyCode())
        {
            s1=false;
        }

        if(j==e.getKeyCode())
        {
            s2=false;
        }
    }

    public void keyTyped(KeyEvent e) {
        //System.out.println("Ty");
    }

    /** Handle the key pressed event from the text field. */
    public void keyPressed(KeyEvent e) {
        System.out.println("pre"+e.getKeyCode());

        if(i==e.getKeyCode())
        {
            s1=true;
        }

        if(j==e.getKeyCode())
        {
            s2=true;
        }

        if(s1==true && s2==true)
        {
            System.out.println("EXIT NOW");
            System.exit(0);
        }
    }

    /** Handle the key released event from the text field. */

}

但是如果其他键也必须是非修饰键呢?比如,用于在屏幕上移动精灵的方向键和用于射击的空格键?您希望能够在移动时进行射击。 - TheRealChx101

2
一般来说,你所描述的可以使用位掩码实现。

你是什么意思,Janusz?这非常相关。是的,它与Java无关,但这并不意味着它没有帮助。 - Mathias Lykkegaard Lorenzen

0

哦,我也遇到过这个问题!

我尝试按照找到的教程制作一个简单的乒乓球游戏。

但是很多时候,如果我按住一个按钮并按下另一个按钮,新的按键似乎会注册,而之前的按键似乎停止注册,即使我仍然按住按键。

我认为这可能是KeyListener功能的限制,因此我尝试重写我的程序以使用Keybindings。

但是,如果有什么不同,它只会让情况变得更糟。

所以我意识到问题在于我正在遵循的教程。 它在监听键后处理逻辑的方式。

因此,如果您遇到此类问题,我建议您排除您正在使用的代码!

还要注意,键的行为显然可以根据您的操作系统而有所不同。

因此,在Windows中,当按下键时,它将像您在文本编辑器中知道的那样重复。 因此,当按下键时,它实际上会重复调用,然后在释放时会给您一个释放事件。

所以请注意这一点!

还值得注意的是,不同的键盘将对同时按下的键数有不同的限制,而该数字通常也会因所按下的键的组合而有所不同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接