Detectores de eventos

Los detectores de eventos, también llamados controladores de eventos, son funciones que ejecuta Flash Player como respuesta a eventos específicos. El proceso de añadir un detector de eventos consta de dos pasos. En primer lugar se debe crear una función o método de clase para que Flash Player lo ejecute como respuesta al evento. Esto a veces recibe el nombre de función de detector o función de controlador de eventos. En segundo lugar, es necesario usar el método addEventListener() para registrar la función de detector en el destino del evento o en cualquier objeto de la lista de visualización que se encuentre en el trayecto del flujo del evento adecuado.

Subtemas

Creación de funciones de detector
Administración de detectores de eventos
Eventos de error sin detectores

Creación de funciones de detector

La creación de funciones de detector es un área en la que el modelo de eventos de ActionScript 3.0 difiere del modelo de eventos DOM. En este último existe una clara distinción entre un detector de eventos y una función de detector: un detector de eventos es una instancia de una clase que implementa la interfaz EventListener, mientras que una función de detector es un método de esa clase denominado handleEvent(). En el modelo de eventos DOM, se debe registrar la instancia de la clase que contiene la función de detector en lugar de la función de detector en sí.

En el modelo de eventos de ActionScript 3.0 no hay distinción entre un detector de eventos y una función de detector. ActionScript 3.0 carece de una interfaz EventListener y es posible definir las funciones de detector fuera de una clase o como parte de ella. Además, no es necesario que las funciones de detector se denominen handleEvent(), sino que pueden usar cualquier identificador válido. En ActionScript 3.0 se registra el nombre de la función de detector real.

Función de detector definida fuera de una clase

El siguiente código crea un archivo SWF sencillo que muestra una forma cuadrada roja. Una función de detector denominada clickHandler(), que no forma parte de ninguna clase, detecta los eventos de clic del ratón sobre el cuadrado rojo.

package
{
    import flash.display.Sprite;

    public class ClickExample extends Sprite
    {
        public function ClickExample()
        {
            var child:ChildSprite = new ChildSprite();
            addChild(child);
        }
    }
}

import flash.display.Sprite;
import flash.events.MouseEvent;

class ChildSprite extends Sprite
{
    public function ChildSprite()
    {
        graphics.beginFill(0xFF0000);
        graphics.drawRect(0,0,100,100);
        graphics.endFill();
        addEventListener(MouseEvent.CLICK, clickHandler);
    }
}

function clickHandler(event:MouseEvent):void
{
    trace("clickHandler detected an event of type: " + event.type);
    trace("the this keyword refers to: " + this);
}

Cuando el usuario interactúa con el archivo SWF resultante haciendo clic en el cuadrado, Flash Player genera la siguiente salida de traza:

clickHandler detected an event of type: click
the this keyword refers to: [object global]

Cabe destacar que el objeto de evento se pasa como argumento a clickHandler(). Esto permite a la función de detector examinar el objeto de evento. En este ejemplo se usa la propiedad type del objeto de evento para determinar si se trata de un evento de clic.

En el ejemplo también se comprueba el valor de la palabra clave this. En este caso, this representa el objeto global, lo cual es totalmente lógico, ya que la función se ha definido fuera de todo objeto o clase personalizada.

Función de detector definida como método de clase

El siguiente ejemplo es idéntico al anterior en el que se define la clase ClickExample, excepto en que la función clickHandler() se define como un método de la clase ChildSprite:

package
{
    import flash.display.Sprite;

    public class ClickExample extends Sprite
    {
        public function ClickExample()
        {
            var child:ChildSprite = new ChildSprite();
            addChild(child);
        }
    }
}

import flash.display.Sprite;
import flash.events.MouseEvent;

class ChildSprite extends Sprite
{
    public function ChildSprite()
    {
        graphics.beginFill(0xFF0000);
        graphics.drawRect(0,0,100,100);
        graphics.endFill();
        addEventListener(MouseEvent.CLICK, clickHandler);
    }
    private function clickHandler(event:MouseEvent):void
    {
        trace("clickHandler detected an event of type: " + event.type);
        trace("the this keyword refers to: " + this);
    }
}

Cuando el usuario interactúa con el archivo SWF resultante haciendo clic en el cuadrado rojo, Flash Player genera la siguiente salida de traza:

clickHandler detected an event of type: click
the this keyword refers to: [object ChildSprite]

La palabra clave this hace referencia a la instancia de ChildSprite denominada child. Esto constituye un cambio en el comportamiento con respecto a ActionScript 2.0. Todos aquellos que usaban componentes en ActionScript 2.0 sin duda recordarán que, al pasar un método de clase a UIEventDispatcher.addEventListener(), el ámbito del método estaba vinculado al componente que difundía el evento en lugar de a la clase en la que estaba definido el método de detector. Dicho de otro modo, si se usara esta técnica en ActionScript 2.0, la palabra clave this haría referencia al componente que realiza la difusión en lugar de a la instancia de ChildSprite.

Esto constituía un problema significativo para algunos programadores, ya que implicaba que no podían acceder a otros métodos y propiedades de la clase que contenía el método detector. Como solución, los programadores de ActionScript 2.0 podían usar la clase mx.util.Delegate para cambiar el ámbito del método detector. Esto ya no es necesario, ya que ActionScript 3.0 crea un método vinculado cuando se llama a addEventListener(). A consecuencia de ello, la palabra clave this hace referencia a la instancia de ChildSprite denominada child y el programador puede acceder a los demás métodos y propiedades de la clase ChildSprite.

Detector de eventos de uso no recomendado

Existe una tercera técnica, que no se recomienda, en la que se crea un objeto genérico con una propiedad que señala a una función de detector asignada dinámicamente. La única razón por la que se trata aquí es porque se utilizaba con frecuencia en ActionScript 2.0, aunque no debe usarse en ActionScript 3.0. Esta técnica no es recomendable porque la palabra clave this hace referencia al objeto global en lugar de al objeto de detector.

El siguiente ejemplo es idéntico al anterior de la clase ClickExample, excepto en que la función de detector se define como parte de un objeto genérico denominado myListenerObj:

package
{
    import flash.display.Sprite;

    public class ClickExample extends Sprite
    {
        public function ClickExample()
        {
            var child:ChildSprite = new ChildSprite();
            addChild(child);
        }
    }
}

import flash.display.Sprite;
import flash.events.MouseEvent;

class ChildSprite extends Sprite
{
    public function ChildSprite()
    {
        graphics.beginFill(0xFF0000);
        graphics.drawRect(0,0,100,100);
        graphics.endFill();
        addEventListener(MouseEvent.CLICK, myListenerObj.clickHandler);
    }
}

var myListenerObj:Object = new Object();
myListenerObj.clickHandler = function (event:MouseEvent):void
{
        trace("clickHandler detected an event of type: " + event.type);
        trace("the this keyword refers to: " + this);
}

El resultado de la traza es el siguiente:

clickHandler detected an event of type: click
the this keyword refers to: [object global]

Cabría esperar que this hiciera referencia a myListenerObj y que la salida de traza fuese [object Object] pero, en vez de eso, hace referencia al objeto global. Al pasar el nombre de una propiedad dinámica como un argumento a addEventListener(), Flash Player no puede crear un método vinculado. Esto se debe a que lo que se pasa como parámetro listener no es más que la dirección de memoria de la función de detector y Flash Player es incapaz de vincular esa dirección de memoria con la instancia de myListenerObj.

Administración de detectores de eventos

Es posible administrar las funciones de detector usando los métodos de la interfaz IEventDispatcher. La interfaz IEventDispatcher es la versión de ActionScript 3.0 de la interfaz EventTarget del modelo de eventos DOM. Si bien el nombre IEventDispatcher parece implicar que su objetivo principal es enviar (o distribuir) objetos de evento, en realidad los métodos de esta clase se usan con mucha más frecuencia para registrar detectores de eventos, comprobar su existencia y eliminarlos. La interfaz IEventDispatcher define cinco métodos, según se muestra en el siguiente código:

package flash.events
{
    public interface IEventDispatcher
    {
        function addEventListener(eventName:String, 
                        listener:Object,
                        useCapture:Boolean=false,
                        priority:Integer=0,
                        useWeakReference:Boolean=false):Boolean;

        function removeEventListener(eventName:String, 
                    listener:Object,
                    useCapture:Boolean=false):Boolean;

        function dispatchEvent(eventObject:Event):Boolean;

        function hasEventListener(eventName:String):Boolean;
        function willTrigger(eventName:String):Boolean;
    }
}

La API de Flash Player implementa la interfaz IEventDispatcher con la clase EventDispatcher, que sirve como clase base de todas las clases que pueden ser destinos de eventos o parte de un flujo de eventos. Por ejemplo, la clase DisplayObject hereda de la clase EventDispatcher. Esto quiere decir que cualquier objeto de la lista de visualización tiene acceso a los métodos de la interfaz IEventDispatcher.

Adición de detectores de eventos

El método addEventListener() es el elemento más ampliamente utilizado de la interfaz IEventDispatcher. Se utiliza para registrar las funciones de detector. Los dos parámetros necesarios son type y listener. Se puede usar el parámetro type para especificar el tipo de evento. El parámetro listener, por su parte, se emplea para especificar la función de detector que se ejecutará cuando se produzca el evento. El parámetro listener puede ser una referencia a una función o a un método de clase.

NOTA

 

No se deben usar paréntesis al especificar el parámetro listener. Por ejemplo, la función clickHandler() se especifica sin paréntesis en la siguiente llamada al método addEventListener():
addEventListener(MouseEvent.CLICK, clickHandler).

El parámetro useCapture del método addEventListener() permite controlar la fase del flujo del evento en la que estará activa el detector. Si useCapture se establece en true, el detector estará activo durante la fase de captura del flujo del evento. Si useCapture se establece en false, el detector estará activo durante las fases de destino y de propagación del flujo del evento. Para detectar un evento durante todas las fases del flujo del evento se debe llamar a addEventListener() dos veces, una con useCapture establecido en true y luego otra con useCapture establecido en false.

El parámetro priority del método addEventListener() no es parte oficial del modelo de eventos DOM de nivel 3. Se incluye en ActionScript 3.0 para ofrecer una mayor flexibilidad a la hora de organizar los detectores de eventos. Cuando se llama a addEventListener(), es posible establecer la prioridad de ese detector de eventos pasando un valor entero como parámetro priority. El valor predeterminado es 0, pero se le pueden asignar valores enteros negativos o positivos. Cuanto mayor sea el número, antes se ejecutará el detector de eventos. Los detectores de eventos con la misma prioridad se ejecutan en el orden en que se añadieron, de modo que cuanto antes se añada, antes se ejecutará.

El parámetro useWeakReference permite especificar si la referencia a la función de detector es débil o normal. Si este parámetro se establece como true se pueden evitar situaciones en las que las funciones de detector permanecen en memoria incluso cuando ya no se necesitan. Flash Player usa una técnica llamada eliminación de datos innecesarios para borrar de la memoria objetos que han dejado de usarse. Se considera que un objeto ha dejado de usarse si no existe ninguna referencia a él. El recolector de datos innecesarios descarta las referencias débiles, de modo que una función de detector que sólo señala a una referencia débil puede ser eliminada, al considerarse como datos innecesarios.

Una consecuencia importante de este parámetro implica la utilización de eventos de objetos de visualización. Normalmente, se espera que un objeto de visualización se borre de la memoria cuando se elimina de la lista de visualización. No obstante, si otros objetos se han suscrito como detectores a ese objeto de visualización y su parámetro useWeakReference tiene el valor false (el predeterminado), el objeto de visualización seguirá existiendo en la memoria de Flash Player aunque ya no aparezca en pantalla. Para solucionar este problema, es necesario que todos los detectores se suscriban al objeto de visualización con el parámetro useWeakReference establecido como true o bien eliminar todos los detectores de eventos del objeto de visualización usando el método removeEventListener().

Eliminación de detectores de eventos

Se puede usar el método removeEventListener() para eliminar los detectores de eventos que ya no sean necesarios. Es aconsejable eliminar todos los detectores que no vayan a usarse más. Los parámetros necesarios son eventName y listener, que son los mismos que para el método addEventListener(). Conviene recordar que se pueden detectar eventos durante todas las fases de eventos llamando a addEventListener() dos veces, una vez con useCapture establecido en true y luego otra establecido en false. Para eliminar los dos detectores de eventos sería necesario llamar a removeEventListener() dos veces, una con useCapture establecido en true y luego otra establecido en false.

Distribución de eventos

Los programadores expertos pueden usar el método dispatchEvent() para distribuir un objeto de evento personalizado en el flujo del evento. Este método sólo acepta un parámetro, consistente en una referencia a un objeto de evento, que debe ser una instancia de la clase Event o una subclase de ésta. Una vez distribuido, la propiedad target del objeto de evento se establece en el objeto en el que se llamó a dispatchEvent().

Comprobación de la existencia de detectores de eventos

Los dos últimos métodos de la interfaz IEventDispatcher ofrecen información útil sobre la existencia de detectores de eventos. El método hasEventListener() devuelve true si se encuentra un detector de eventos para un tipo de evento específico en un objeto concreto de la lista de visualización. El método willTrigger() también devuelve true si se encuentra un detector para un objeto concreto de la lista de visualización, pero willTrigger() no sólo comprueba la existencia de detectores en el objeto de la lista de visualización, sino también en todos los ascendientes del objeto de la lista de visualización para todas las fases del flujo del evento.

Eventos de error sin detectores

Las excepciones, y no los eventos, son el principal mecanismo de gestión de errores en ActionScript 3.0, pero la gestión de excepciones no funciona en operaciones asíncronas, como la carga de archivos. Si se produce un error durante una de estas operaciones asíncronas, Flash Player distribuye un objeto de evento de error. Si no se crea un detector para el evento de error, la versión de depuración de Flash Player mostrará un cuadro de diálogo con información acerca del error. Por ejemplo, si se usa un URL no válido al cargar un archivo, en la versión de depuración de Flash Player aparece el siguiente cuadro de diálogo:


Imagen de mensaje de error de Flash Player. El mensaje indica que se produjo un error de ActionScript, seguido de una identificación del error como un error de flujo con un URL en particular. Hay dos botones para descartar todo o continuar.

La mayor parte de los eventos de error se basan en la clase ErrorEvent y, por tanto, tienen una propiedad denominada text que se usa para almacenar el mensaje de error que muestra Flash Player. Las dos excepciones a esta regla son las clases StatusEvent y NetStatusEvent. Ambas clases tienen una propiedad level (StatusEvent.level y NetStatusEvent.info.level). Cuando el valor de la propiedad level es "error", estos tipos de evento se consideran eventos de error.

Un evento de error no hace que el archivo SWF deje de ejecutarse. Sólo se manifestará como un cuadro de diálogo en las versiones de depuración de los plug-ins de navegadores y de los reproductores autónomos, como un mensaje en el panel de salida del reproductor de edición y como una entrada en el archivo de registro de Adobe Flex Builder 2. En las versiones comerciales de Flash Player no aparecerá en absoluto.


Flash CS3

 

Enviarme un mensaje de correo electrónico cuando se añadan comentarios a esta página | Informe de comentarios

Página actual: http://livedocs.adobe.com/flash/9.0_es/main/00000139.html