5 Stimmen

Java KeyListener ist verzögerte Registrierung

Wie die meisten Leute mittlerweile wissen, registriert Java in der keyPressed-Methode einen Tastendruck, hält dann für etwa eine halbe Sekunde inne und zeichnet dann einen stetigen Strom von Tastendrücken auf. Mein Problem ist, dass ich möchte, dass Java sofort einen stetigen Strom von keyDown-Ereignissen aufzeichnet, sobald eine Taste gedrückt wird. Ich habe viele Artikel zu diesem Problem gelesen, und in vielen davon ist von Swing-Timern die Rede, über die ich ebenfalls im Dunkeln tappe. Um das folgende Stück Code hübscher und übersichtlicher zu gestalten, habe ich einfach das Fett weggeschnitten und den Key Listener in eine eigene Klasse gepackt! Jeder Beitrag zu diesem Thema wäre sehr willkommen!

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

    }
}

7voto

Nick Rippe Punkte 6455

Wenn eine gedrückte Taste ein Auslöser ist, um die GUI zu aktualisieren, dann müssen Sie SwingTimers einbinden. Wenn es keine Aktualisierung der GUI auslöst, können Sie einfach normale Threads verwenden.

Ich nehme an, die Artikel beziehen sich auf folgende Punkte

  1. Speichern, welche Tasten gedrückt werden, mit der KeyListener
  2. Mit einem Swing Timer prüfen, welche Tasten in bestimmten Intervallen (z. B. alle 100 ms) gedrückt werden.

Hier ist ein Beispiel dafür, wie Sie das in Ihr Projekt einbauen könnten 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){}
    }

Hier ist ein Beispiel, bei dem alles zusammengefügt ist - ein Etikett wird aktualisiert, das genau angibt, welche Tasten gedrückt werden (nach Tastencode).

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

}

Editar

Bitte beachten Sie auch die von @HovercraftFullOfEels geposteten Warnungen über KeyListener . Je nachdem, was Sie erreichen wollen, sollten Sie die Verwendung von Schlüsselbindungen in Betracht ziehen (es gilt das gleiche Prinzip wie in diesem Beitrag). Hier ist eine nützliche Lehrgang auf Key Bindings, wenn Sie einen Blick darauf werfen möchten.

6voto

Ich denke, dass dies kein Java-Problem, sondern eher ein Problem des Betriebssystems ist - das Betriebssystem verzögert das Senden von Tastenanschlägen um eine bestimmte Zeit, bevor es einen Strom von Tastenanschlägen sendet. Eine Lösung ist das Starten eines Swing Timers beim Drücken einer Taste. Ich würde auch empfehlen, dass Sie Key Bindings anstelle eines KeyListener verwenden.

Außerdem geben Sie an, dass Sie "im Dunkeln tappen", was Swing Timer angeht. Wenn dem so ist, empfehle ich Ihnen dringend, das zu tun, was der Rest von uns getan hat, wenn wir in dieser Situation waren: Schauen Sie sich das entsprechende Tutorial an. Mit Google finden Sie es recht schnell. Auch eine Suche auf dieser Website wird Ihnen helfen, Beispiele für die Verwendung von Tastenkombinationen mit einem Swing Timer zu finden, zum Beispiel aquí .

Editar
KeyListener ist ein Low-Level-Konstrukt, und im Allgemeinen sollten Sie es vorziehen, Konstrukte auf höherer Ebene zu verwenden, da sie sicherer und einfacher zu verwenden sind, ohne Nebenwirkungen oder Probleme zu verursachen. Zum Beispiel kann es leicht zu Problemen mit dem Fokus kommen, wenn Sie einen KeyListener verwenden, da er nur funktioniert, wenn die Komponente, auf die er hört, den Fokus hat. Dies kann leicht umgangen werden, wenn Sie stattdessen Tastenbindungen verwenden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X