4

正如大多数人现在对按键监听器所意识到的那样,在 keyPressed 方法中,java 会记录一次按键,然后暂停大约半秒,然后记录您按键的稳定流。我的问题是,一旦按下一个键,我希望 java 立即注册一个稳定的流 keyDown 事件。我已经阅读了很多关于这个问题的文章,其中很多都谈到了摆动计时器,我对此也一无所知。为了让下面的代码更好看,我只是剪掉了胖子,把关键的监听器放到一个单独的类中!对此的任何意见将不胜感激!

public class Keyer implements KeyListener
{

    Keyer(){}
    @Override
    public void keyPressed(KeyEvent ovent)
    {
        int keyCode = ovent.getKeyCode();
        System.out.println("You pressed: "+keyCode);
    }
    @Override
    public void keyReleased(KeyEvent ovent)
    {

    }
    @Override
    public void keyTyped(KeyEvent ovent)
    {

    }
}
4

2 回答 2

6

我认为这不是 Java 问题,而是操作系统问题——操作系统在发送击键流之前会延迟发送击键一段时间。一种解决方案是在按键时启动 Swing Timer。我还建议您使用 Key Bindings 而不是 KeyListener。

您还说您对摇摆计时器“一无所知”,如果是这样,我敦促您在这种情况下做我们其他人所做的事情:查看相关教程。谷歌会帮助你很快找到它。此外,搜索此站点将帮助您找到将键绑定与 Swing Timer 一起使用的示例,例如,请查看此处

编辑
KeyListener 是一个低级构造,通常您应该更喜欢使用更高级别的构造,因为它们更安全、更易于使用而不会产生副作用或出现问题。例如,如果使用 KeyListener 很容易遇到焦点问题,因为它仅在监听的组件具有焦点时才有效。如果您改用键绑定,这很容易避免。

于 2012-08-24T03:05:18.620 回答
6

如果按下的键是更新 GUI 的触发器,那是您需要合并 SwingTimers 的时候。如果它没有触发对您的 GUI 的更新,您可以只使用普通线程。

我认为这些文章所指的是

  1. 使用KeyListener
  2. 使用 Swing Timer 检查在给定的时间间隔(比如每 100 毫秒)按下了哪些键

以下是如何将其合并到您的示例KeyListener

    public class Keyer implements KeyListener{

        /** Stores currently pressed keys */
        HashSet<Integer> pressedKeys = new HashSet<Integer>();

        public Keyer(){

            //Check every 100ms if there's keys pressed
            //(This is the Swing Timer they talk about)
            new Timer(100, new ActionListener(){
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    String keysString = "";
                    if(!pressedKeys.isEmpty()){
                        Iterator<Integer> i = pressedKeys.iterator();
                        while(i.hasNext()){
                            keysString += i.next() + ",";
                        }
                    } 
                    System.out.println(keysString);
                }
            }).start();
        }

        @Override
        public void keyPressed(KeyEvent ovent){
            //Add key to hashSet when pressed
            int keyCode = ovent.getKeyCode();
            pressedKeys.add(keyCode);
        }
        @Override
        public void keyReleased(KeyEvent ovent){
            //Remove key from hashset when released
            int keyCode = ovent.getKeyCode();
            pressedKeys.remove(keyCode);
        }
        @Override
        public void keyTyped(KeyEvent ovent){}
    }

这是一个将所有内容放在一起的示例 - 更新的标签告诉您确切按下了哪些键(通过键码)。

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

public class TempProject extends JPanel{
    /** Label to update with currently pressed keys */
    JLabel output = new JLabel();

    public TempProject(){
        super();
        setFocusable(true);
        add(output, BorderLayout.CENTER);
        requestFocus();
        addKeyListener(new Keyer());
    }

    public static void main(String args[])
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
                frame.setContentPane(new TempProject());    
                frame.pack();
                frame.setVisible(true);
                new TempProject();
            }
        });
    }

    public class Keyer implements KeyListener{

        /** Stores currently pressed keys */
        HashSet<Integer> pressedKeys = new HashSet<Integer>();

        public Keyer(){

            //Check every 100ms if there's keys pressed
            //(This is the Swing Timer they talk about)
            new Timer(100, new ActionListener(){
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    String keysString = "";
                    if(!pressedKeys.isEmpty()){
                        Iterator<Integer> i = pressedKeys.iterator();
                        while(i.hasNext()){
                            keysString += i.next() + ",";
                        }
                    } 
                    output.setText(keysString);
                }
            }).start();
        }

        @Override
        public void keyPressed(KeyEvent ovent){
            //Add key to hashSet when pressed
            int keyCode = ovent.getKeyCode();
            pressedKeys.add(keyCode);
        }
        @Override
        public void keyReleased(KeyEvent ovent){
            //Remove key from hashset when released
            int keyCode = ovent.getKeyCode();
            pressedKeys.remove(keyCode);
        }
        @Override
        public void keyTyped(KeyEvent ovent){}
    }



}

编辑

另外,请参阅@HovercraftFullOfEels 发布的关于KeyListener. 根据您要完成的工作,您可能需要考虑使用键绑定(与本文应用的原理相同)。如果您想看一下,这里有一个关于键绑定的有用教程。

于 2012-08-24T03:47:16.353 回答