Ecouteurs d’événement

Flash Player 9 et les versions ultérieures, Adobe AIR 1.0 et les versions ultérieures

Les écouteurs d’événement, également appelés gestionnaires d’événements, sont des fonctions que Flash Player et AIR exécutent en réponse à des événements déterminés. La procédure d’ajout d’un écouteur d’événement se déroule en deux temps. En premier lieu, vous créez une fonction ou méthode de classe que Flash Player ou AIR doit exécuter en réponse à l’événement. On parle parfois de fonction d’écouteur ou de fonction de gestionnaire d’événement. En second lieu, vous utilisez la méthode addEventListener() pour enregistrer la fonction d’écouteur auprès de la cible de l’événement ou tout autre objet de la liste d’affichage qui appartient au flux d’événements approprié.

Création d’une fonction d’écouteur

La création d’une fonction d’écouteur est un domaine dans lequel le modèle d’événements ActionScript 3.0 diffère du modèle d’événements DOM. Dans le modèle d’événements DOM, on distingue clairement un écouteur d’événement et une fonction d’écouteur : un écouteur d’événement est une occurrence de classe qui implémente l’interface EventListener, tandis qu’une fonction d’écouteur est une méthode de cette classe appelée handleEvent(). Dans le modèle d’événements DOM, vous enregistrez l’occurrence de classe qui contient la fonction d’écouteur, plutôt que la fonction d’écouteur elle-même.

Le modèle d’événements ActionScript ne fait aucune distinction entre l’écouteur d’événement et la fonction d’écouteur. L’interface EventListener est inexistante dans ActionScript 3.0 et les fonctions d’écouteur peuvent être définies en dehors de toute classe ou au sein d’une classe. Par ailleurs, il n’est pas nécessaire de nommer les fonctions d’écouteur handleEvent() ; vous pouvez utiliser tout identifiant valable. Dans ActionScript 3.0, vous enregistrez le nom de la fonction d’écouteur elle-même.

Fonction d’écouteur définie en dehors de toute classe

Le code suivant crée un fichier SWF simple qui affiche une forme carrée de couleur rouge. Une fonction d’écouteur appelée clickHandler(), qui n’appartient à aucune classe, écoute les événements de clic de souris dans le carré rouge.

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); 
}

Lorsqu’un utilisateur interagit avec le fichier SWF résultant, en cliquant sur le carré, Flash Player ou AIR génère la sortie de suivi ci-après :

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

Notez que l’objet événement est transmis sous forme d’instruction à clickHandler(). Cela permet à votre fonction d’écouteur d’examiner l’objet événement. Dans cet exemple, vous utilisez la propriété type de l’objet événement pour vérifier que cet événement correspond à un clic.

L’exemple vérifie aussi la valeur du mot-clé this. Dans ce cas, this représente l’objet global, ce qui est logique puisque la fonction est définie en dehors de toute classe ou objet personnalisé.

Fonction d’écouteur définie comme méthode de classe

L’exemple ci-dessous est identique au précédent, qui définit la classe ClickExample, sauf que la fonction clickHandler() est définie comme méthode de la classe 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); 
    } 
}

Lorsqu’un utilisateur interagit avec le fichier SWF résultant, en cliquant sur le carré rouge, Flash Player ou AIR génère la sortie de suivi ci-après :

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

Notez que le mot-clé this renvoie à l’occurrence de ChildSprite appelée child. Voici un changement de comportement par rapport à ActionScript 2.0. Si vous utilisiez des composants dans ActionScript 2.0, vous vous rappelez sans doute que lorsqu’une méthode de classe était transmise à UIEventDispatcher.addEventListener(), l’étendue de la méthode était liée au composant qui émettait l’événement, et non à la classe dans laquelle la méthode d’écouteur était définie. En d’autres termes, si vous utilisiez cette technique dans ActionScript 2.0, le mot-clé this renvoyait au composant émettant l’événement et non à l’occurrence de ChildSprite.

Pour certains développeurs, il s’agissait d’un vrai problème car cela signifiait qu’ils ne pouvaient accéder à aucune autre méthode et propriété de la classe qui contenait la méthode d’écouteur. Pour le contourner, les programmeurs d’ActionScript 2.0 pouvaient utiliser la classe mx.util.Delegate pour modifier l’étendue de la méthode d’écouteur. Cette manipulation n’est plus nécessaire puisque ActionScript 3.0 crée une méthode liée lorsque addEventListener() est appelée. Par conséquent, le mot-clé this fait référence à l’occurrence de ChildSprite appelée child et le programmeur peut accéder aux autres méthodes et propriétés de la classe ChildSprite.

Ecouteur d’événement à ne pas utiliser

Une troisième technique permet de créer un objet générique dont l’une des propriétés pointe vers une fonction d’écouteur affectée dynamiquement. Elle est cependant déconseillée. Nous l’évoquons ici en raison de son utilisation courante dans ActionScript 2.0 ; il n’est toutefois pas recommandé de l’utiliser dans ActionScript 3.0. Cette mise en garde tient au fait que le mot-clé this fera référence à l’objet global et non à l’objet écouteur.

L’exemple ci-après est identique à l’exemple précédent de la classe ClickExample, sauf que la fonction d’écouteur est définie comme faisant partie d’un objet générique appelé 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); 
}

Les résultats de trace seront les suivants :

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

On s’attendrait à ce que this fasse référence à myListenerObj et que la sortie de suivi soit [object Object], mais le mot-clé renvoie en fait à l’objet global. Lorsque vous transmettez un nom de propriété dynamique comme instruction à addEventListener(), Flash Player ou AIR est incapable de créer une méthode liée. En effet, ce que vous transmettez comme paramètre listener n’est rien de plus que l’adresse mémoire de votre fonction d’écouteur ; Flash Player et AIR n’ont aucun moyen de lier cette adresse à l’occurrence de myListenerObj.

Gestion des écouteurs d’événement

Vous pouvez gérer vos fonctions d’écouteur à l’aide des méthodes de l’interface IEventDispatcher. Cette interface est la version ActionScript 3.0 de l’interface EventTarget du modèle d’événements DOM. Bien que le nom IEventDispatcher semble impliquer que l’objet principal de la classe est l’envoi (ou la distribution) des objets événements, les méthodes qui lui correspondent servent en fait plus souvent à l’enregistrement, la vérification et la suppression des écouteurs d’événement. L’interface IEventDispatcher définit cinq méthodes, comme illustré dans le code suivant :

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; 
    } 
}

L’API de Flash Player implémente l’interface IEventDispatcher à l’aide de la classe Event Dispatcher. Cette dernière constitue la classe de base de toutes les classes pouvant servir de cibles d’événement ou faire partie d’un flux d’événements. Par exemple, la classe DisplayObject hérite de la classe EventDispatcher, par conséquent, tout objet de la liste d’affichage peut accéder aux méthodes de l’interface IEventDispatcher.

Ajout des écouteurs d’événement

La méthode addEventListener() est la clé de voûte de l’interface IEventDispatcher. Elle permet d’enregistrer les fonctions d’écouteurs. Les deux paramètres requis sont type et listener. Le paramètre type spécifie le type d’événement. Avec le paramètre listener, vous pouvez spécifier la fonction d’écouteur qui doit s’exécuter lorsque l’événement survient. Le paramètre listener peut être une référence à une fonction ou une méthode de classe.

n’utilisez pas de parenthèses pour stipuler le paramètre listener. Par exemple, la fonction clickHandler() est spécifiée sans parenthèses dans l’appel suivant à la méthode addEventListener() :
addEventListener(MouseEvent.CLICK, clickHandler)

Le paramètre useCapture de la méthode addEventListener() vous permet de contrôler la phase du flux d’événements pendant laquelle votre écouteur sera actif. Si useCapture a la valeur true, votre écouteur sera actif pendant la phase de capture du flux d’événements. Si useCapture a la valeur false, votre écouteur sera actif pendant la phase cible et la phase de propagation du flux d’événements. Pour écouter un événement pendant toutes les phases du flux d’événements, vous devez appeler deux fois addEventListener() ; la première fois, useCapture prend la valeur true, la seconde fois, useCapture prend la valeur false.

Le paramètre priority de la méthode addEventListener() ne fait pas officiellement partie du modèle d’événements DOM de niveau 3. Il est inclus dans ActionScript 3.0 pour vous offrir une plus grande souplesse dans l’organisation de vos écouteurs d’événement. Lorsque vous appelez addEventListener(), vous pouvez définir la priorité de cet écouteur d’événement en transmettant une valeur entière comme paramètre priority. La valeur par défaut est 0. Vous pouvez toutefois utiliser une valeur entière négative ou positive. Plus le nombre est élevé, plus l’exécution de l’écouteur d’événement est rapide. Les écouteurs d’événement de priorité équivalente sont exécutés suivant l’ordre dans lequel ils ont été ajoutés : plus l’écouteur est ajouté tôt, plus il est exécuté rapidement.

Le paramètre useWeakReference vous permet de spécifier si la référence à la fonction d’écouteur est faible ou normale. En lui attribuant la valeur true, vous évitez les situations dans lesquelles les fonctions d’écouteurs demeurent dans la mémoire alors qu’elles sont inutiles. Flash Player et AIR utilisent une technique appelée nettoyage pour effacer de la mémoire les objets qui ne servent plus. Un objet est considéré comme inutilisé lorsqu’il n’apparaît dans aucune référence. Le nettoyeur de mémoire ignore les références faibles, c’est-à-dire qu’une fonction d’écouteur vers laquelle pointe uniquement une référence faible est incluse dans le nettoyage.

Suppression des écouteurs d’événement

La méthode removeEventListener() permet de supprimer un écouteur d’événement dont vous n’avez plus besoin. Il est judicieux de supprimer tous les écouteurs qui ne seront plus utilisés. Les paramètres requis sont notamment eventName et listener, soit les mêmes que ceux requis pour la méthode addEventListener(). Rappel : pour écouter les événements pendant toutes les phases du flux d’événements, vous pouvez appeler addEventListener() deux fois, en attribuant à useCapture la valeur true la première, puis false la seconde. Pour supprimer les deux écouteurs d’événement, il serait nécessaire d’appeler removeEventListener() à deux reprises, la première fois en attribuant la valeur true à useCapture, la seconde fois en utilisant la valeur false.

Distribution d’événements

La méthode dispatchEvent() peut servir aux développeurs chevronnés pour distribuer un objet événement personnalisé dans le flux d’événements. Cette méthode accepte un seul paramètre, une référence à l’objet événement, qui doit être une occurrence de la classe Event ou de l’une de ces sous-classes. Après distribution, la propriété target de l’objet événement est définie avec l’objet sur lequel portait l’appel dispatchEvent().

Vérification des écouteurs d’événement existants

Les deux dernières méthodes de l’interface IEventDispatcher fournissent des informations précieuses sur l’existence des écouteurs d’événement. La méthode hasEventListener() renvoie la valeur true si un écouteur d’événement est détecté pour un type d’événement spécifique sur un objet particulier de la liste d’affichage. La méthode willTrigger() renvoie également la valeur true si un écouteur est détecté pour un objet donné de la liste d’affichage. Cependant willTrigger() vérifie les écouteurs sur l’objet d’affichage en question mais également sur tous les ascendants de cet objet dans l’ensemble des phases du flux d’événements.

Evénements d’erreur sans écouteurs

Plus que les événements, les exceptions constituent le mécanisme principal de gestion des erreurs dans ActionScript 3.0. Toutefois, la gestion des exceptions ne fonctionne pas sur les opérations asynchrones telles que les chargements de fichiers. Si une erreur survient pendant une opération asynchrone, Flash Player et AIR distribuent un objet événement d’erreur. Si vous ne créez pas d’écouteur pour l’événement d’erreur, les versions de débogage de Flash Player et AIR affichent une boîte de dialogue comportant des informations sur l’erreur en question. Par exemple, la version de débogage de Flash Player affiche la boîte de dialogue suivante, qui décrit l’erreur associée à une tentative de chargement d’un fichier par l’application à partir d’une URL non valide :

La plupart des événements d’erreur reposent sur la classe ErrorEvent. Ils présentent donc une propriété appelée text, qui sert au stockage du message d’erreur que Flash Player ou AIR affiche. Il existe deux exceptions : les classes StatusEvent et NetStatusEvent. Ces deux classes possèdent une propriété level (StatusEvent.level et NetStatusEvent.info.level). Lorsque la valeur de la propriété level est error, ces types d’événement sont considérés comme des événements d’erreur.

Un événement d’erreur n’interrompt pas l’exécution du fichier SWF. Il se traduit uniquement par l’affichage d’une boîte de dialogue dans les versions de débogage des navigateurs et des lecteurs autonomes, d’un message dans le panneau de sortie du lecteur de création et d’une entrée dans le fichier journal d’Adobe Flash Builder. Aucune manifestation n’est visible dans les autres versions de Flash Player ou AIR.