【问题标题】:How do I run the key event only once even if the key is hold?即使键被按住,我如何只运行一次键事件?
【发布时间】:2021-10-24 18:57:53
【问题描述】:

我在使用 Java 8 制作游戏时测试此代码。

public void keyReleased(KeyEvent e) {
    int keycode = e.getKeyCode();

    switch( keycode ) { 
        case 37:
            System.out.println("left");
            break;
        case 39:
            System.out.println("right");
            break;
        case 38:
            System.out.println("up");
            break;
        case 40:
            System.out.println("down");
            break;
    }
}

我发现当我按住箭头键时,它会多次打印出那个键名,直到我松开它。如果我希望它只打印一次键名,即使我按住键(并再次打印,直到我释放并再次按下它),我该怎么办?

我查看了文档,但它说:

由于操作系统处理键重复的方式,按住 key 可能会导致多次调用 keyPressed() (和 keyReleased() 为 出色地)。重复率由操作系统设置,每个 电脑配置好了。 (结束自动生成)

【问题讨论】:

  • @Abra 感谢您的评论,但我仍然对如何做到这一点感到困惑,您能给我举个关于如何使用getWhen 的例子吗?
  • 在游戏中,您最有可能对按下或已按下哪个键感兴趣。 Keylistner 只会让您头疼,因为它不是为实时轮询键盘而设计的。相反,您应该有一个类检查原始 awt 事件队列并跟踪按下的键。您的程序会定期检查这一点。然后处理多个按键就变得更容易了。
  • 我刚刚发现气垫船回答了这个好问题:

标签: java


【解决方案1】:

调用方法getWhen 以查找连续调用方法keyReleased 之间经过的时间。如果经过的时间小于特定量(例如半秒,即 500 毫秒),那么您知道该键被按住。顺便说一句,在 Windows 10 上使用 Java 11 时,我没有这种行为。键名只打印一次。

试试下面的示例应用。

import java.awt.EventQueue;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JTextField;

public class GetsWhen implements KeyListener {

    /** Maximum elapsed time to consider key held down. */
    private static final long THRESHOLD = 500L;

    /** Timestamp of last invocation of method 'keyReleased'. */
    private long lastWhen;

    @Override // java.awt.event.KeyListener
    public void keyTyped(KeyEvent e) {
        // Not implemented.
    }

    @Override // java.awt.event.KeyListener
    public void keyPressed(KeyEvent e) {
        // Not implemented.
    }

    @Override // java.awt.event.KeyListener
    public void keyReleased(KeyEvent e) {
        long when = e.getWhen();
        long diff = when - lastWhen;
        if (diff > THRESHOLD) {
            int keycode = e.getKeyCode();
            switch (keycode) {
                case 37:
                    System.out.println("left");
                    break;
                case 39:
                    System.out.println("right");
                    break;
                case 38:
                    System.out.println("up");
                    break;
                case 40:
                    System.out.println("down");
                    break;
            }
        }
        lastWhen = when;
    }

    private void createAndDisplayGui() {
        JFrame frame = new JFrame("When");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JTextField textField = new JTextField(10);
        textField.addKeyListener(this);
        frame.add(textField);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new GetsWhen().createAndDisplayGui());
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多