2010-10-14 13 views
8

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

+0

Questa è una bella analisi sulla gestione di KeyEvent ... ma non so se è effettivamente una domanda che è comprensibile. – BoffinbraiN

+0

@BoffinbraiN: Speravo che qualcuno con qualche dozzina di badge swing dicesse qualcosa come "per quanto ne so io sia corretto" :) –

+1

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

risposta

1

Abbiamo bisogno di avviare il debug da Component.dispatchEventImpl.
Basta leggere i commenti di origine del metodo per darti l'idea perfetta di come gli eventi fluiscono in Swing (puoi anche iniziare un livello su da EventQueue.pumpEventsForHeirarchy).

Per chiarezza solo lasciatemi fare un estratto dal codice:

  1. Set timestamp e modificatori di evento corrente .; Pre-dispatcher. Effettua qualsiasi retargeting/riordino necessario qui prima di notificare AWTEventListeners.
  2. Consenti al Toolkit di passare questo evento a AWTEventListeners.
  3. Se nessuno ha consumato un evento chiave, consentire a KeyboardFocusManager di elaborarlo.
  4. Consentire metodi di input per elaborare l'evento
  5. Pre-processo tutti gli eventi speciali prima della consegna
  6. Deliver evento per l'elaborazione normale
  7. una gestione speciale per 4.061.116:. Gancio per il browser per chiudere le finestre di dialogo modali :)
  8. Permetti al peer di elaborare l'evento. Tranne KeyEvents, saranno trattati da pari, dopo tutti KeyEventPostProcessors (vedi DefaultKeyboardFocusManager.dispatchKeyEvent())

ora che è possibile abbinare il flusso di sopra con la tua descrizione per determinare se il suo giusto o no. Ma il punto è che non dovresti davvero dipendere da javadoc di classi private, il motivo è che di solito gli sviluppatori non si preoccupano di aggiornare i commenti delle classi private quando il codice cambia, quindi i documenti potrebbero diventare obsoleti.

Problemi correlati