Java KeyListener是延迟注册

Ben*_*gel 4 java swing timer keylistener delay

正如大多数人现在用密钥监听器实现的那样,在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)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

Hov*_*els 6

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

你还说你在摇摆计时器"黑暗中",如果是这样,我敦促你做我们其他人在这种情况下所做的事情:检查相关的教程.Google会帮助您快速找到它.此外,搜索此站点将帮助您查找使用Swing Timer进行键绑定的示例,例如,请查看此处.

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

  • @BenHagel`KeyListeners`也倾向于在其他更好的方法应用的地方使用,例如尝试过滤文本组件. (3认同)

Nic*_*ppe 6

如果按下的键是更新GUI的触发器,则需要使用SwingTimers.如果它没有触发GUI的更新,则可以使用普通线程.

我认为文章所指的是

  1. 保存使用的按键 KeyListener
  2. 使用Swing Timer检查按给定间隔按下哪些键(比如每100ms)

以下是如何将其纳入您的示例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){}
    }
Run Code Online (Sandbox Code Playgroud)

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

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){}
    }



}
Run Code Online (Sandbox Code Playgroud)

编辑

另外,请参阅@HovercraftFullOfEels发布的警告KeyListener.根据您要完成的任务,您可能需要考虑使用Key Bindings(与此帖适用的原理相同).如果你想看一下,这是关于键绑定的有用教程.

  • 谈论_meta_上的问题而不是这里的答案:-)实际上有了这个帖子,我还没有决定 - OP的(假定的)上下文可能在奇数用例中很好,这实际上需要一个keyListener(绑定不能轻易处理keyEvents的强制重启 (2认同)