Cómo escribir un Oyente de Focus

Muchos componentes --incluso aquellos que operan primariamente con el ratón, como los botones -- pueden operar con el teclado. Parea que una pulsación afecte a un componente, este debe tener el foco del teclado.

Desde el punto de vista del usuario, el componente que tiene el foco del teclado generalmente es más priminente -- con un borde más ancho que el usual, por ejemplo -- y la ventana que contiene el componente también es más priminente que las otras ventanas de la pantalla. Estos aspectos visuales permiten al usuario conocer a qué componente le va a teclear. Al menos un componente del sistema de ventanas tiene el foco del teclado.

Los eventos Focus se generan cuando un componente gana o pierde el foco del teclado. El modo exacto en que los componentes ganan o pierden el foco depende del sistema de ventanas. Típicamente, el usuario selecciona el foco pulsando una ventana o componente, haciendo TAB entre componentes, o mediante otra forma de interactuar con el componente, Una vez que el foco está en una ventana (la ventana está activada) un programa puede usar el método requestFocus de Component para requerir que un componente específico tenga el foco.

Métodos de Eventos Focus

El interface FocusListener y su correspondiente clase adaptadora, FocusAdapter, contienen dos métodos :
void focusGained(FocusEvent)
Se le llama después de que el componente escuchado obtenga el foco.
void focusLost(FocusEvent)
Se le llama después de que el componente escuchado pierda el foco.

Ejemplos de Manejo de Eventos Focus

El siguiente applet demuestra los eventos focus. Pulsando sobre el botón superior del applet, se mostrará una ventana que contiene una veriedad de componentes. Un oyente de focus escucha todos los eventos de este tipo incluidos los de la propia ventana (que es un ejemplar de una subclase de JFrame llamada FocusWindow).

Click this figure to run the applet.
Esta es una imagen del GUI del Applet. Para ejecutarlo, pulsa sobre ella. El applet aparecerá en una nueva ventana de tu navegador.

Prueba esto:
  1. Despliega la ventana pulsando el botón superior del applet.
    si es necesario, pulsa sobre la ventana "Focus Event Window" para su contenido obtenga el foco del teclado. Veras que aparece un mensaje "Focus gained" en el área del applet. La forma en que la ventana obtiene o pierde el foco depende del sistema. Podemos detectar cuando una ventana gana o pierde el foco implementando un oyente de window y escuchando los eventos window activation o deactivation.
  2. Pulsa el botón que hay a la derecha de la ventana, y luego pulsa otro componente, como un campo de texto.
    Observa que cuando el foco cambia de un componente a otro, el primer componente genera un evento focus-lost antes de que el segundo componente genere un evento focus-gained.
  3. Intenta cambiar el foco pulsao Tab o Shift-Tab.
    La mayoría de los sistemas permiten usan la tecla Tab para circular a través de los componentes que pueden obtener el foco.
  4. Minimiza la ventana "Focus Event Window".
    Deberías ver un mensaje "Focus lost" desde el último componente que lo tenía.

Puedes encontrar el código del applet en FocusEventDemo.java. Aquí está el código de manejo de eventos:

public class FocusEventDemo ... implements FocusListener ... {
	...//where initialization occurs
	window = new FocusWindow(this);
    ...
    public void focusGained(FocusEvent e) {
	displayMessage("Focus gained", e);
    }

    public void focusLost(FocusEvent e) {
	displayMessage("Focus lost", e);
    }

    void displayMessage(String prefix, FocusEvent e) {
	display.append(prefix
		       + ": "
		       + e.getComponent()
		       + newline); 
    }
    ...
}

class FocusWindow extends JFrame {
    ...
    public FocusWindow(FocusListener listener) {
	super("Focus Demo Window");
	this.addFocusListener(listener);
	...
	JLabel label = new JLabel("A Label");
	label.addFocusListener(listener);
	...
	JComboBox choice = new JComboBox(/* list of items */);
	...
	choice.addFocusListener(listener);
	...
	JButton button = new JButton("A Button");
	button.addFocusListener(listener);
	...
	JList list = new JList(/* list of items */);
	...
	list.addFocusListener(listener);
    }
}

La clase FocusEvent

Cada método de evento focus tiene un sólo parámetro: un objeto FocusEvent, La clase FocusEvent define el siguiente método:
boolean isTemporary()
Devuelve true si la pérdida del foco es temporal. Necesitaremos utilizar este método si estamos implementando un componente que pueda indicar que obtendrá el foco cuando la ventana lo vuelva a obtener.
El método getComponent, que FocusEvent hereda de ComponentEvent, devuelve el componente que genero el evento de focus.

Ozito