Ho letto il tutorial definito su key bindings un paio di volte, ma il mio cache del cervello non sembra abbastanza grande da contenere i processi complicati.In che modo Java invia KeyEvents?
ero il debug di un problema di legame chiave (rivelato stavo usando il torto JComponent.WHEN_*
condizione), e sono incappato in un javadoc conciso e divertente per il pacchetto privato javax.swing.KeyboardManager
da una (purtroppo) anonimo ingegnere Java.
La mia domanda è questa: ad eccezione di KeyEventDispatcher
che viene controllata all'inizio, la descrizione manca e/o errore qualcosa?
La classe KeyboardManager viene utilizzata per aiuto azioni della tastiera spedizione per la WHEN_IN_FOCUSED_WINDOW azioni di stile. Le azioni con altre condizioni sono gestite direttamente in JComponent.
Ecco una descrizione dei symantics [sic] di come tastiera dispacciamento dovrebbe funzionare atleast [sic] come ho capito.
KeyEventi vengono inviati al componente focalizzato . Il focus manager ottiene il primo crack durante l'elaborazione di questo evento . Se il responsabile della messa a fuoco non lo desidera, il JComponent chiama super.processKeyEvent(), ciò consente agli ascoltatori di di elaborare l'evento .
Se nessuno degli ascoltatori "consuma" l'evento, le associazioni di tasti ottengono uno scatto . È qui che le cose iniziano a diventare interessanti. Innanzitutto, KeyStokes [sic] definiti con la condizione WHEN_FOCUSED hanno una possibilità. Se nessuno dei desidera l'evento, il componente cammina sebbene sia [sic] i genitori cercassero le azioni di tipo WHEN_ANCESTOR_OF_FOCUSED_COMPONENT.
Se nessuno lo ha ancora preso, allora lo finisce qui. Quindi cerchiamo i componenti registrati per gli eventi WHEN_IN_FOCUSED_WINDOW e attiviamo . Notare che se nessuno di quelli viene trovato, si passa l'evento a alla barra dei menu e si lascia che abbiano una crepa . Sono gestiti in modo diverso.
Infine, controlliamo se stiamo guardando una cornice interna. Se siamo e no uno voleva l'evento, quindi ci spostiamo su per il creatore di InternalFrame e vedere se qualcuno vuole l'evento (e così via e così via).
(UPDATE) Se vi siete mai chiesti su questo avviso in grassetto nella guida chiave binding:
Perché l'ordine di cercare i componenti è imprevedibile, evitare di duplicare WHEN_IN_FOCUSED_WINDOW attacchi!
E 'a causa di questo segmento 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;
}
}
Così l'ordine di ricerca è in realtà prevedibile, ma ovviamente dipende da questa particolare implementazione, quindi è meglio non fare affidamento su a tutti. Tienilo imprevedibile.
(Javadoc e il codice da jdk1.6.0_b105 su WinXP.)
Questa è una bella analisi sulla gestione di KeyEvent ... ma non so se è effettivamente una domanda che è comprensibile. – BoffinbraiN
@BoffinbraiN: Speravo che qualcuno con qualche dozzina di badge swing dicesse qualcosa come "per quanto ne so io sia corretto" :) –
Sì, sarebbe stato sicuramente preferibile! Ma penso che per qualcosa di così profondo, sia davvero specifico per l'implementazione, e tu abbia scrutato questa implementazione molto più attentamente di quanto lo faranno i programmatori più diligenti. ;) Meglio non rendere il tuo codice dipendente da questo specifico dettaglio, ovviamente. – BoffinbraiN