J'ai lu le tutoriel définitif sur key bindings à quelques reprises, mais mon cache de cerveau ne semble pas assez grand pour contenir les processus complexes.Comment Java envoie-t-il les KeyEvents?
je débogage un problème de liaison clé (avéré que j'utilisais le mauvais état JComponent.WHEN_*
), et je suis tombé sur un javadoc concis et hilarant pour le privé javax.swing.KeyboardManager
paquet par un (malheureusement) ingénieur Java anonyme.
Ma question est la suivante: sauf pour KeyEventDispatcher
qui est vérifié au tout début, est-ce que la description manque et/ou se trompe?
La classe KeyboardManager est utilisé pour aide les actions du clavier d'expédition pour les WHEN_IN_FOCUSED_WINDOW actions de style. Les actions avec d'autres conditions sont traitées directement dans JComponent.
Voici une description des symantics [sic] de la façon dont le clavier dispatching devrait fonctionner atleast [sic] que je comprends . KeyEvents sont expédiés au composant ciblé
Le gestionnaire de focus obtient le premier crack au traitement de cet événement . Si le gestionnaire de focus ne le souhaite pas, le JComponent appelle super.processKeyEvent() ceci permet aux écouteurs de traiter l'événement .
Si aucun des écouteurs ne "consomme" l'événement, les raccourcis clavier obtiennent un tir . C'est là que les choses commencent à devenir intéressantes. Tout d'abord, KeyStokes [sic] défini avec la condition WHEN_FOCUSED avoir une chance. Si aucun de ne souhaite l'événement, le composant se déplace alors que c'est [sic] les parents ont recherché des actions de type WHEN_ANCESTOR_OF_FOCUSED_COMPONENT. Si personne ne l'a encore pris, alors il finit ici. Nous recherchons ensuite les composants enregistrés pour les événements WHEN_IN_FOCUSED_WINDOW et leur envoyons . Notez que si aucun de ces n'est trouvé, alors nous passons l'événement à les menubars et nous leur laissons une fissure . Ils sont gérés différemment.
Enfin, nous vérifions si nous regardons un cadre interne. Si nous sommes et aucun voulu l'événement alors nous montons au créateur de l'InternalFrame et voir si quelqu'un veut l'événement (et ainsi de suite et ainsi de suite).
(UPDATE) Si vous avez déjà demandé cet avertissement gras dans le guide clé bindings:
Parce que l'ordre de recherche des composants est imprévisible, éviter de dupliquer WHEN_IN_FOCUSED_WINDOW fixations!
Il est à cause de ce segment 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;
}
}
Ainsi, l'ordre de recherche est en fait prévisible, mais dépend évidemment de cette mise en œuvre particulière, il est donc préférable pas compter sur du tout. Gardez-le imprévisible.
(Javadoc et le code est de jdk1.6.0_b105 sur Windows XP.)
Ceci est une belle analyse sur la gestion de KeyEvent ... mais je ne sais pas si c'est une question qui est responsable. – BoffinbraiN
@BoffinbraiN: J'espérais que quelqu'un avec quelques douzaines de badges de swing dit quelque chose comme "au meilleur de ma connaissance c'est correct" :) –
Oui, cela aurait certainement été préférable! Mais je pense que pour quelque chose d'aussi profond, c'est vraiment lié à la mise en œuvre, et vous avez scruté cette implémentation avec beaucoup plus de soin que la plupart des programmeurs diligents. ;) Bien sûr, ne pas faire dépendre votre code de ce détail spécifique, bien sûr. – BoffinbraiN