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?
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);
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);
}
}
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);
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 .
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
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;
}
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;
}
}
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);
}
}
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");
}
});
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.