## Reglas Generales para escribir Oyentes de Eventos

Cuando el AWT llama a un método oyente de evento, este método se ejecuta en el thread de eventos del AWT. Como todos los demás manejos de eventos y los métodos de dibujo se ejecutan en el mismo thread, un lento método de manejo de eventos puede hacer que el programa parezca no responder y puede relentizar el propio dibujado.

> Importante: Aseguráte de que tus métodos de oyentes de eventos se ejecutan rápidamente!

Si necesitas realizar alguna operación lenta como resultado de un evento, hazlo arrancado otro thread (o enviando una petición a otro thread) para realizar la operación.

La siguiente subsección presenta el ascentro de todas las clases evento del AWT, la clase AWTEvent. Depués, Usar adaptadores y Clases Internas para Manejar Eventos AWT te ofrecerá trucos para evitar un código borroso..

#### La clase AWTEvent

> Todo método en un interface oyente de evento del AWT tiene un sólo argumento, un ejemplar de una clase que descienda de la clase java.awt.AWTEvent. Esta clase no define ningún método o API que podamos usar normalmente. Sin embargo, hereda un método muy útil de la clase java.util.EventObject:
> Object getSource()
>   devuelve el objeto que generó el evento.
> Observa que el método getSource devuelve un Object. Siempre que sea posible, las subclases de AWTEvent definen métodos similares con tipos de retorno más restrictivos. Por ejemplo, la clase ComponentEvent define un método getComponent que devuelve el Component que generó el evento.

> LA figura 68 muestra la herencia de clases de AWTevent. Como se puede ver muchas, pero no todas, las clases de eventos del AWT descienden de la clase ComponentEvent.

> El árbol de herencia de las clases de eventos AWT:

#### Eventos Estandard del AWT

> El AWT define cerca de una docena de tipos de oyentes de eventos. Se puede decir los tipos de eventos que puede generar un componente mirando las clases de oyentes de eventos que podemos registrar en él. Por ejemplo, la clase Component define estos métodos de registros de oyentes:
> - addComponentListener
> - addFocusListener
> - addKeyListener
> - addMouseListener
> - addMouseMotionListener
> Por lo tanto, toda clase que descienda de Component soporta oyentes de component, focus, key, mouse y mouse-motion. Sin embargo la mayoría de los ejemplares de Component no generan estos eventos; un componnete genera sólo aquellos eventos para los que los oyentes se han registrado. Por ejemplo, so un oyente de mouse se regostra en un componente particular, y el componente no tiene otros oyentes, entonces el componente sólo generara eventos de mouse.

#### Usar Adaptadores y Clases Internas para Manejar Eventos

> Esta sección explica cómo utilizar adaptadores y clases internas para reducir la sobrecarga del código. Si no importa este sujeto, puedes saltar libremente a la siguiente sección.

> La mayoría de los interfaces de oyentes, al contrario que ActionListener, contienen más de un método. Por ejemplo, el interface MouseListener contiene cinco métodos:mousePressed, mouseReleased, mouseEntered, mouseExited, y mouseClicked. Incluso si sólo te importan las pulsaciones, si tu clase implementa directamente MouseListener, entonces debes implementar los cinco métodos de MouseListener. Aquellos métodos de eventos que no te interesan pueden tener los cuerpos vacíos. Aquí hay un ejemplo:

>     //An example with cluttered but valid code.
>     public class MyClass implements MouseListener {
>         ...
>     	someObject.addMouseListener(this);
>         ...
>         /* Empty method definition. */
>         public void mousePressed(MouseEvent e) {
>         }

>         /* Empty method definition. */
>         public void mouseReleased(MouseEvent e) {
>         }

>         /* Empty method definition. */
>         public void mouseEntered(MouseEvent e) {
>         }

>         /* Empty method definition. */
>         public void mouseExited(MouseEvent e) {
>         }

>         public void mouseClicked(MouseEvent e) {
>     	...//Event handler implementation goes here...
>         }
>     }

Desafortunadamente, la colección de cuerpos de métodos vacios resultante puede resultar dura de leer y de mantener. Para ayudarnos a evitar este emborronamiento del código con cuerpos de métodos vacios, el AWT y Swing proporcionan una clase adapter por cada interface de oyente con más de un método. (Manejar Eventos Comunes lista todos los oyentes y sus adaptadores.) Por ejemplo, la clase MouseAdapter implmenta el interface MouseListener. Una clase adaptador implementa versiones vacías de todos los métodos del interface.

Para usar un adaptador se crea una subclase, en vez de implementar directamente un interface de oyente. Por ejemplo, extendiendo la clase MouseAdapter, nuestra clase hereda definiciones de vacías para los métodos que contiene MouseListener.

    /*
     * An example of extending an adapter class instead of
     * directly implementing a listener interface.
     */
    public class MyClass extends MouseAdapter {
        ...
    	someObject.addMouseListener(this);
        ...
        public void mouseClicked(MouseEvent e) {
    	...//Event handler implementation goes here...
        }
    }

¿Qué pasa si no queremos que nuestras clases de manejo de eventos desciendan de una clase adaptador? Por ejemplo, supongamos que escribimos un applet, y queremos que nuestra subclase Applet contenga algún método para manejar eventos de ratón. Como el lenguaje Java no permite la herencia múltiple, nuestra clase no puede descender de las clases Applet y MouseAdapter. La solución es definir una clase interna -- una clase dentro de nuestra subclase Applet -- que descienda de la clase MouseAdapter,

    //An example of using an inner class.
    public class MyClass extends Applet {
        ...
    	someObject.addMouseListener(new MyAdapter());
        ...
        class MyAdapter extends MouseAdapter {
            public void mouseClicked(MouseEvent e) {
    	    ...//Event handler implementation goes here...
            }
        }
    }

Aquí hay otro ejemplo de uso de clases internas:

    //An example of using an anonymous inner class.
    public class MyClass extends Applet {
        ...
    	someObject.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
    	        ...//Event handler implementation goes here...
                }
    	});
        ...
        }
    }

Las clases internas funcionan bien incluso si nuestro manejador de eventos necesita acceder a ejemplares de variables privadas de la clase que la encierra. Siempre que no declaremos una clase interna como static, se podrá referir a ejemplares de variables y métodos como lo hace el resto de código que contiene la clase. Para hacer que una variable local esté disponible para una clase interna solo tenemos que hacer un copia de la variable como una variable local final.

> Nota: Algunos compiladores 1.1 no permiten a las clases internas acceder a ejemplares de variables privados de la clase que la encierra. Un atajo es eliminar el especificador private de la declaración del ejemplar de la variable.

Ozito