Ich habe das definitive Tutorial auf key bindings ein paar Mal gelesen, aber mein Gehirn Cache scheint nicht groß genug, um die komplizierten Prozesse zu halten.Wie versendet Java KeyEvents?
Ich war eine Schlüsselbindungsproblem Debugging (stellte sich heraus ich die falsche JComponent.WHEN_*
Zustand wurde mit), und ich stolperte über eine prägnante und urkomisch javadoc für das Paket privaten javax.swing.KeyboardManager
durch eine (leider) anonym Java Ingenieur.
Meine Frage ist dies: außer KeyEventDispatcher
, die am Anfang überprüft wird, fehlt die Beschreibung und/oder etwas falsch?
Die KeyboardManager Klasse wird für die zu Hilfe Versandtastaturaktionen verwendet WHEN_IN_FOCUSED_WINDOW Stil Aktionen. Aktionen mit anderen Bedingungen werden direkt in JComponent behandelt.
Hier ist eine Beschreibung der symantics [sic], wie Tastatur Dispatching funktionieren sollte atleast [sic], wie ich es verstehe .
KeyEvents werden an die fokussierte Komponente gesendet. Der Focus Manager bekommt den ersten Fehler bei der Verarbeitung dieses Ereignisses. Wenn der Fokus-Manager es nicht will, dann ruft die JComponent super.processKeyEvent() das ermöglicht Listener eine Chance, das Ereignis zu verarbeiten.
Wenn keiner der Listener das Ereignis " " konsumiert, erhalten die Tastatureingaben eine Aufnahme. Dies ist, wo Dinge zu beginnen interessant werden. Zuerst erhalten KeyStokes [sic], die mit dem WHEN_FOCUSED Zustand definiert werden, eine Chance. Wenn keiner von diese das Ereignis wünschen, dann geht die Komponente durch, es ist [sic] Eltern suchte nach Aktionen des Typs WHEN_ANCESTOR_OF_FOCUSED_COMPONENT.
Wenn noch niemand es genommen hat, dann geht es hier oben . Wir suchen dann nach Komponenten, die für WHEN_IN_FOCUSED_WINDOW Ereignisse registriert sind und feuern zu ihnen. Beachten Sie, dass wenn keine gefunden wird, übergeben wir das Ereignis an die Menüleisten und lassen Sie einen Riss bei ihm haben. Sie werden anders behandelt.
Schließlich überprüfen wir, ob wir einen internen Rahmen betrachten. Wenn wir sind und keine man wollte das Ereignis, dann bewegen wir uns auf den Ersteller des InternalFrame und sehen , wenn jemand das Ereignis will (und so weiter und so weiter).
(UPDATE) Wenn Sie jemals über diese mutige Warnung in der Tastenbelegungen Führung gefragt haben:
Da die Reihenfolge der Suche der Komponenten ist unberechenbar, Vermeiden Sie doppelte WHEN_IN_FOCUSED_WINDOW Bindungen!
Es ist wegen dieses Segments in KeyboardManager#fireKeyboardAction
:
Object tmp = keyMap.get(ks);
if (tmp == null) {
// don't do anything
} else if (tmp instanceof JComponent) {
...
} else if (tmp instanceof Vector) { //more than one comp registered for this
Vector v = (Vector)tmp;
// There is no well defined order for WHEN_IN_FOCUSED_WINDOW
// bindings, but we give precedence to those bindings just
// added. This is done so that JMenus WHEN_IN_FOCUSED_WINDOW
// bindings are accessed before those of the JRootPane (they
// both have a WHEN_IN_FOCUSED_WINDOW binding for enter).
for (int counter = v.size() - 1; counter >= 0; counter--) {
JComponent c = (JComponent)v.elementAt(counter);
//System.out.println("Trying collision: " + c + " vector = "+ v.size());
if (c.isShowing() && c.isEnabled()) { // don't want to give these out
fireBinding(c, ks, e, pressed);
if (e.isConsumed())
return true;
}
}
So ist die Reihenfolge der Suche ist tatsächlich vorhersehbar, aber natürlich abhängig von dieser speziellen Implementierung, so dass es besser ist, nicht vertrauen es überhaupt. Halte es unberechenbar.
(Javadoc und Code ist aus jdk1.6.0_b105 auf WinXP.)
Dies ist eine gute Analyse zum KeyEvent-Handling ... aber ich weiß nicht, ob es tatsächlich eine Frage ist, die beantwortbar ist. – BoffinbraiN
@BoffinbraiN: Ich hatte gehofft, dass jemand mit ein paar Dutzend Swing-Abzeichen so etwas wie "nach meinem besten Wissen ist es korrekt" sagt :) –
Ja, das wäre definitiv besser gewesen! Aber ich denke, für so etwas tiefgründiges ist es wirklich implementierungsspezifisch, und Sie haben diese Implementierung viel sorgfältiger untersucht als die meisten fleißigen Programmierer jemals. ;) Am besten machen Sie Ihren Code natürlich nicht von diesem speziellen Detail abhängig. – BoffinbraiN