KeyListener如何处理多个按键被按下? [英] KeyListener how to handle multiple keys pressed?

查看:65
本文介绍了KeyListener如何处理多个按键被按下?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我在Java中有一个按键侦听器,该按键侦听器在JFrame上向上,向下,向左或向右移动一个矩形,为此我使用W,A,S和D键.通常,尤其是在游戏中,按2个键将产生对角线移动.例如,您同时按下W和D键,预期的行为是向右斜向上移动.但是,密钥侦听器一次只能检测到一个密钥.我知道我可以做一些事情,一次检测多个密钥,然后像编写新密钥一样编写新代码,但是有没有办法同时在两个不同的密钥下执行两个代码呢?如果没有,我如何一次测试多个键?

So I have a key listener in Java that moves a rectangle on a JFrame either up, down, left, or right for which I am using the W, A, S, and D keys. Usually, and especially in games, pressing 2 keys should yeild diagonal movement. An example would be you press W and D at the same time, and the expected behavior is to move diagonally to the right upwards. However, the key listener only detects one key at a time. I know I can do something where I detect multiple keys at a time and then write new code as if it were a new key but is there a way to execute two pieces of code under two different keys at the same time? If not, how can I test multiple keys at a time?

这是一个最小的可复制对象,它设置了一个矩形,该矩形可以使用W,A,S和D键移动.

Here is a minimal reproducible that sets up a rectangle that moves with the W, A, S, and D keys.

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

public class Test extends JPanel implements KeyListener {
    
    private int x = 200, y = 200;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Test().create();
    }
    
    public void paintComponent(Graphics tool) {
        super.paintComponent(tool);
        tool.drawRect(x,  y, 50, 50);
    }
    
    public void create() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 500);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        
        frame.add(this);
        frame.addKeyListener(this);
        
        frame.setVisible(true);
    }

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

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        switch(e.getKeyCode()) {
        case KeyEvent.VK_W:
            y -= 3;
            break;
        case KeyEvent.VK_S:
            y += 3;
            break;
        case KeyEvent.VK_A:
            x -= 3;
            break;
        case KeyEvent.VK_D:
            x += 3;
            break;
        }
        repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub
        
    }

}

推荐答案

因此,在@Maarten Bodewes提出了一些建议之后,我想出了以下解决方案:

So after some of @Maarten Bodewes 's advice, I came up with this solution:

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import java.util.*;

public class Test extends JPanel implements KeyListener {
    
    private int x = 200, y = 200;
    
    Set<Integer> keys = new HashSet<Integer>();

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Test().create();
    }
    
    public void paintComponent(Graphics tool) {
        super.paintComponent(tool);
        tool.drawRect(x,  y, 50, 50);
    }
    
    public void create() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 500);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        
        frame.add(this);
        frame.addKeyListener(this);
        
        frame.setVisible(true);
    }

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

    @Override
    public void keyPressed(KeyEvent e) {
        // TODO Auto-generated method stub
        keys.add(e.getKeyCode());
        multiKeys();
        repaint();
    }
    
    public void multiKeys() {
        System.out.println(keys.size());
        for(Integer key: keys) {
            System.out.println(key);
            switch(key) {
            case KeyEvent.VK_W:
                y -= 3;
                break;
            case KeyEvent.VK_S:
                y += 3;
                break;
            case KeyEvent.VK_A:
                x -= 3;
                break;
            case KeyEvent.VK_D:
                x += 3;
                break;
            }
        }
    }


    @Override
    public void keyReleased(KeyEvent e) {
        // TODO Auto-generated method stub
        keys.remove(e.getKeyCode());
        
    }

}

现在,当我按"W"和"D"时,矩形将按预期的对角线方向移动.这是由于以下事实:名为 keys 的Set存储了按下的键,然后通过称为 multiKeys()的单独方法执行了这些键的代码,该方法循环了.当然,当不再按下某个键时,可以通过KeyListener keyReleased()方法将其从 keys 集中删除.

Now when I press say W and D, the rectangle moved diagonally as intended. This is due to the fact that a Set called keys stores the keys pressed, and then executes those keys' codes through a separate method called multiKeys() which loops keys. And of course when a key is no longer pressed, remove it from the keys Set via the KeyListener keyReleased() method.

这篇关于KeyListener如何处理多个按键被按下?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆