it-swarm.com.de

Nicht reagierender KeyListener für JFrame

Ich versuche, ein KeyListener für mein JFrame zu implementieren. Auf dem Konstruktor verwende ich diesen Code:

System.out.println("test");
addKeyListener(new KeyListener() {
    public void keyPressed(KeyEvent e) { System.out.println( "tester"); }

    public void keyReleased(KeyEvent e) { System.out.println("2test2"); }

    public void keyTyped(KeyEvent e) { System.out.println("3test3"); }
});

Wenn ich es starte, erscheint die Nachricht test in meiner Konsole. Wenn ich jedoch eine Taste drücke, erhalte ich keine der anderen Nachrichten, als wäre das KeyListener nicht einmal da.

Ich dachte, das könnte daran liegen, dass der Fokus nicht auf dem JFrame liegt.
und so erhalten sie KeyListener keine Ereignisse. Aber ich bin mir ziemlich sicher, dass es so ist.

Fehlt mir etwas?

77
Tomek

Sie müssen Ihren keyListener zu jeder benötigten Komponente hinzufügen. Nur die Komponente mit dem Fokus sendet diese Ereignisse. Wenn Sie beispielsweise nur eine TextBox in Ihrem JFrame haben, hat diese TextBox den Fokus. Daher müssen Sie auch dieser Komponente einen KeyListener hinzufügen.

Der Prozess ist der gleiche:

myComponent.addKeyListener(new KeyListener ...);

Hinweis: Einige Komponenten wie JLabel können nicht fokussiert werden.

Um sie fokussierbar zu machen, müssen Sie:

myComponent.setFocusable(true);
46
bruno conde

Wenn Sie nicht für jede Komponente einen Listener registrieren möchten,
Sie könnten fügen Sie Ihr eigenes KeyEventDispatcher hinz zum KeyboardFocusManager:

public class MyFrame extends JFrame {    
    private class MyDispatcher implements KeyEventDispatcher {
        @Override
        public boolean dispatchKeyEvent(KeyEvent e) {
            if (e.getID() == KeyEvent.KEY_PRESSED) {
                System.out.println("tester");
            } else if (e.getID() == KeyEvent.KEY_RELEASED) {
                System.out.println("2test2");
            } else if (e.getID() == KeyEvent.KEY_TYPED) {
                System.out.println("3test3");
            }
            return false;
        }
    }
    public MyFrame() {
        add(new JTextField());
        System.out.println("test");
        KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
        manager.addKeyEventDispatcher(new MyDispatcher());
    }

    public static void main(String[] args) {
        MyFrame f = new MyFrame();
        f.pack();
        f.setVisible(true);
    }
}
126
Peter

InputMaps und ActionMaps wurden entwickelt, um die Schlüsselereignisse für die Komponente, sie und alle ihre Unterkomponenten oder das gesamte Fenster zu erfassen. Dies wird über den Parameter in JComponent.getInputMap () gesteuert. Dokumentation finden Sie unter Verwendung von Tastenkombinationen .

Das Schöne an diesem Design ist, dass man auswählen kann, welche Tastenanschläge zu überwachen sind, und dass verschiedene Aktionen basierend auf diesen Tastenanschlägen ausgelöst werden.

Dieser Code ruft dispose () in einem JFrame auf, wenn die Escape-Taste an einer beliebigen Stelle im Fenster gedrückt wird. JFrame leitet sich nicht von JComponent ab, daher müssen Sie eine andere Komponente im JFrame verwenden, um die Schlüsselbindung zu erstellen. Das Inhaltsfenster ist möglicherweise eine solche Komponente.

InputMap inputMap; 
ActionMap actionMap;
AbstractAction action;
JComponent component;

inputMap  = component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
actionMap = component.getActionMap();

action    = new AbstractAction()
{
   @Override
   public void actionPerformed(ActionEvent e)
   {
      dispose();
   }
};

inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "dispose");
actionMap.put("dispose", action);
16
Nathan

KeyListener ist niedrig und gilt nur für eine einzelne Komponente. Trotz der Versuche, es benutzerfreundlicher zu machen, erstellt JFrame eine Reihe von Komponentenkomponenten, von denen das Inhaltsfenster das offensichtlichste ist. JComboBox Die Benutzeroberfläche wird häufig auf ähnliche Weise implementiert.

Es ist erwähnenswert, dass die Mausereignisse auf seltsame Weise funktionieren, die sich geringfügig von den wichtigsten Ereignissen unterscheiden.

Einzelheiten dazu, was Sie tun sollten, finden Sie in meiner Antwort unter Anwendungsweite Tastenkombination - Java Swing .

10

Ich habe das gleiche Problem, bis ich gelesen habe, dass das eigentliche Problem bei FOCUS liegt, da Ihr JFrame bereits Listener hinzugefügt hat, der Tour-Frame jedoch nie auf Focus eingestellt ist, da in Ihrem JFrame viele Komponenten enthalten sind, die auch fokussiert werden können. Versuchen Sie Folgendes:

JFrame.setFocusable(true);

Viel Glück

10
Ferkiros

Deion (und jeder andere, der eine ähnliche Frage stellt), können Sie den obigen Code von Peter verwenden, aber anstatt auf Standardausgabe zu drucken, testen Sie den Schlüsselcode PRESSED, RELEASED oder TYPED.

@Override
public boolean dispatchKeyEvent(KeyEvent e) {
    if (e.getID() == KeyEvent.KEY_PRESSED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    } else if (e.getID() == KeyEvent.KEY_RELEASED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    } else if (e.getID() == KeyEvent.KEY_TYPED) {
        if (e.getKeyCode() == KeyEvent.VK_F4) {
            dispose();
        }
    }
    return false;
}
8
Daves

um Schlüsselereignisse von ALLEN Textfeldern in einem JFrame zu erfassen, kann ein Schlüsselereignis-Postprozessor verwendet werden. Hier ist ein funktionierendes Beispiel, nachdem Sie die offensichtlichen Includes hinzugefügt haben.

public class KeyListenerF1Demo extends JFrame implements KeyEventPostProcessor {
    public static final long serialVersionUID = 1L;

    public KeyListenerF1Demo() {
        setTitle(getClass().getName());

        // Define two labels and two text fields all in a row.
        setLayout(new FlowLayout());

        JLabel label1 = new JLabel("Text1");
        label1.setName("Label1");
        add(label1);

        JTextField text1 = new JTextField(10);
        text1.setName("Text1");
        add(text1);

        JLabel label2 = new JLabel("Text2");
        label2.setName("Label2");
        add(label2);

        JTextField text2 = new JTextField(10);
        text2.setName("Text2");
        add(text2);

        // Register a key event post processor.
        KeyboardFocusManager.getCurrentKeyboardFocusManager()
                .addKeyEventPostProcessor(this);
    }

    public static void main(String[] args) {
        JFrame f = new KeyListenerF1Demo();
        f.setName("MyFrame");
        f.pack();
        f.setVisible(true);
    }

    @Override
    public boolean postProcessKeyEvent(KeyEvent ke) {
        // Check for function key F1 pressed.
        if (ke.getID() == KeyEvent.KEY_PRESSED
                && ke.getKeyCode() == KeyEvent.VK_F1) {

            // Get top level ancestor of focused element.
            Component c = ke.getComponent();
            while (null != c.getParent())
                c = c.getParent();

            // Output some help.
            System.out.println("Help for " + c.getName() + "."
                    + ke.getComponent().getName());

            // Tell keyboard focus manager that event has been fully handled.
            return true;
        }

        // Let keyboard focus manager handle the event further.
        return false;
    }
}
4
Hubert Kauker

Hmm .. für welche Klasse ist dein Konstruktor? Wahrscheinlich eine Klasse, die JFrame erweitert? Der Fensterfokus sollte natürlich auf dem Fenster liegen, aber ich glaube nicht, dass das das Problem ist.

Ich habe Ihren Code erweitert, versucht, ihn auszuführen, und er hat funktioniert - die Tastendrücke führten zu einer Druckausgabe. (laufe mit Ubuntu über Eclipse):

public class MyFrame extends JFrame {
    public MyFrame() {
        System.out.println("test");
        addKeyListener(new KeyListener() {
            public void keyPressed(KeyEvent e) {
                System.out.println("tester");
            }

            public void keyReleased(KeyEvent e) {
                System.out.println("2test2");
            }

            public void keyTyped(KeyEvent e) {
                System.out.println("3test3");
            }
        });
    }

    public static void main(String[] args) {
        MyFrame f = new MyFrame();
        f.pack();
        f.setVisible(true);
    }
}
2
Touko

Dies sollte helfen

    yourJFrame.setFocusable(true);
    yourJFrame.addKeyListener(new Java.awt.event.KeyAdapter() {


        @Override
        public void keyTyped(KeyEvent e) {
            System.out.println("you typed a key");
        }

        @Override
        public void keyPressed(KeyEvent e) {
            System.out.println("you pressed a key");
        }

        @Override
        public void keyReleased(KeyEvent e) {
            System.out.println("you released a key");
        }
    });
2
Rahul

Ich habe das gleiche Problem gehabt. Ich bin Brunos Rat gefolgt und habe festgestellt, dass das Hinzufügen eines KeyListener nur zu der "ersten" Schaltfläche im JFrame (dh oben links) den Trick getan hat. Aber ich stimme Ihnen zu, es ist eine Art beunruhigende Lösung. Also habe ich herumgespielt und einen besseren Weg gefunden, das Problem zu beheben. Fügen Sie einfach die Zeile hinzu

myChildOfJFrame.requestFocusInWindow();

zu Ihrer Hauptmethode, nachdem Sie Ihre Instanz Ihrer Unterklasse von JFrame erstellt und sichtbar gemacht haben.

1
pocketdora