¿Cómo despachar Java KeyEvents?
-
30-09-2019 - |
Pregunta
He leído el tutorial definitivo en asociaciones de teclas un par de veces, pero mi caché cerebro no parecen lo suficientemente grande para contener los procesos complicados.
Me depurando una asignación de teclas (resultó que estaba usando la condición JComponent.WHEN_*
mal), y me topé con un conciso y javadoc hilarante para el paquete privado javax.swing.KeyboardManager
por una (por desgracia) ingeniero anónimo Java.
Mi pregunta es la siguiente: a excepción de KeyEventDispatcher
que se comprueba al principio, hace la descripción fallo y / o error nada
La clase KeyboardManager se utiliza para las acciones del teclado ayuda para el despacho acciones WHEN_IN_FOCUSED_WINDOW estilo. Acciones con las demás condiciones son manipulado directamente en JComponent.
He aquí una descripción de las symantics [Sic] de cómo despacho teclado debería funcionar al menos [sic] como yo entiendelo.
KeyEvents se envían a la componente centrado. El gestor de selección obtiene primera grieta en la tramitación del presente evento. Si el gestor de selección no lo hace lo quiere, entonces las llamadas JComponent super.processKeyEvent () esto permite oyentes la oportunidad de procesar la evento.
Si ninguno de los oyentes "consume" el evento, las combinaciones de teclas obtener una Disparo. Aquí es donde las cosas empiezan a ponerse interesante. En primer lugar, keystokes [Sic] definido con la WHEN_FOCUSED condición tienen la oportunidad. Si ninguno de éstos quieren el caso, entonces el camina componente A pesar de que los padres de [sic] buscado acciones de tipo WHEN_ANCESTOR_OF_FOCUSED_COMPONENT.
Si no se ha tomado todavía, entonces vientos de hasta aquí. a continuación, buscamos componentes registrado para WHEN_IN_FOCUSED_WINDOW eventos y fuego a ellos. Tenga en cuenta que si ninguno de los se encuentran a continuación, se pasa el caso a las barras de menú y dejar que ellos tienen una grieta en ella. Están manejan de forma diferente.
Por último, comprobamos si estamos mirando un marco interno. Si somos y sin uno quería el evento, nos movemos hacia arriba al creador y sede de la InternalFrame si alguien quiere el evento (y así sucesivamente y así sucesivamente).
(UPDATE) Si alguna vez se ha preguntado sobre esta advertencia en negrita en la guía de asociaciones de teclas:
Debido a que el fin de buscar los componentes es impredecible, duplicado evitar atascamientos WHEN_IN_FOCUSED_WINDOW!
Es debido a este segmento en 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;
}
}
Así que el orden de búsqueda es en realidad predecible , pero depende obviamente en esta implementación particular, por lo que es mejor no a confiar en él en absoluto. Mantenerlo impredecible.
(Javadoc y el código es de jdk1.6.0_b105 en WinXP.)
Solución
Tenemos que empezar la depuración de Component.dispatchEventImpl .
Sólo la lectura a través de los comentarios de código del método debe darle la idea perfecta de cómo fluyen los eventos de oscilación (también se puede empezar a un nivel por encima de EventQueue.pumpEventsForHeirarchy).
Para mayor claridad, házmelo dar un extracto del código:
- Establecer fecha y hora y modificadores de evento actual .; Pre-despachadores. Hacer cualquier reorientación necesaria / reordenación de aquí antes de que notificamos AWTEventListeners.
- Permitir que el Toolkit para pasar este evento para AWTEventListeners.
- Si nadie ha consumido un evento clave, permitir que el KeyboardFocusManager procesarlo.
- Permitir métodos de entrada para procesar el evento
- Pre-procesar los eventos especiales antes de la entrega
- Deliver eventos para el procesamiento normal manipulación
- Especial para 4061116: Gancho de explorador para cerrar los cuadros de diálogo modales:.)
- Permitir que el peer para procesar el evento. Excepto KeyEvents, que serán procesadas por el par después de que todos KeyEventPostProcessors (ver DefaultKeyboardFocusManager.dispatchKeyEvent ())
Ahora se puede coincidir con el flujo anterior con su descripción para determinar si su derecho o no. Pero el punto es que realmente no debería depender javadocs de clases particulares, la razón es que los desarrolladores de atención normalmente te para actualizar los comentarios de clases particulares cuando los cambios de código, por lo que los documentos pueden llegar a ser obsoletos.