25 February 2007
Débutant
La gestion d'événements dans ActionScript a considérablement évolué dans les dernières versions de Flash Player. Et la sortie d'ActionScript 3.0 confirme cette tendance puisque cette nouvelle version renforce encore le contrôle sur les événements.
Le présent article aborde les nouvelles fonctionnalités liées à la gestion d'événements dans ActionScript 3.0. Vous y découvrirez le fonctionnement de la nouvelle classe EventDispatcher, notamment pour les événements de souris. La propagation d'événements, les objets événement et la création d'événements personnalisés sont également abordés.
Dans ActionScript 3.0, la gestion d'événements dépend fortement de la classe EventDispatcher. Bien que cette classe ne soit pas tout à fait nouvelle, elle fait pour la première fois partie intégrante du langage ActionScript. Peut-être avez-vous également déjà utilisé EventDispatcher dans JavaScript ou ActionScript 2.0 avec des composants V2. Une version externe de la classe EventDispatcher était, en effet, utilisée pour gérer les événements des composants V2. Cette version d'EventDispatcher est toutefois légèrement différente de celle utilisée en interne par ActionScript 3.0.
Pour ceux qui ne connaissent pas cette classe, le concept de base est le suivant : vous créez d'abord des fonctions ou gestionnaires d'événements destinés à réagir à certains événements, puis vous associez ces fonctions aux événements à l'aide de la méthode addEventListener(), appelée depuis l'objet récepteur de l'événement. Le principe est semblable à celui d'ActionScript 2.0 (qui n'utilise pas EventDispatcher), si ce n'est que, dans la version 2.0, le gestionnaire d'événements est défini au sein de l'objet récepteur et que la fonction porte le nom de l'événement reçu. Par exemple, dans ActionScript 2.0, pour qu'une action se déclenche après un événement « onPress » pour un bouton intitulé submitButton, le code à utiliser est le suivant :
submitButton.onPress = function() { ... }
Avec EventDispatcher, les mêmes éléments sont concernés : un objet récepteur de l'événement, un nom d'événement et une fonction réagissant à l'événement. Seul le processus change légèrement. Si vous utilisez EventDispatcher, le code se présente comme suit :
function pressHandler(){ ... }
submitButton.addEventListener("onPress", pressHandler);
Ce qui semble être une étape supplémentaire permet en fait de bénéficier de plus de souplesse. En effet, dans la mesure où vous utilisez une fonction pour ajouter des gestionnaires d'événements au lieu de les définir directement au niveau de l'objet cible, vous avez la possibilité d'ajouter autant de gestionnaires que vous le souhaitez pour « écouter » un seul événement.
Pour retirer des événements dans ActionScript 2.0, vous deviez supprimer le gestionnaire :
delete submitButton.onPress;
Avec EventDispatcher, la méthode removeEventListener() est utilisée. Elle permet de supprimer un écouteur d'événement dont la définition correspond à la définition utilisée dans addEventListener (jusqu'au troisième paramètre).
submitButton.removeEventListener("onPress", pressHandler);
Vous aurez remarqué qu'EventDispatcher n'est pas référencé de façon explicite dans les extraits de code ci-dessus. En réalité, vous utiliserez rarement EventDispatcher directement dans le code. Dans ActionScript 3.0, EventDispatcher est une classe de base que vous étendez avec d'autres classes pour accéder à la méthode addEventListener et à d'autres méthodes. Dans ActionScript 2.0, EventDispatcher était une classe mixin.
Pour assigner ces méthodes à d'autres objets, vous deviez utiliser EventDispatcher.initialize pour les copier dans l'objet souhaité depuis EventDispatcher. Désormais, les classes héritent des méthodes par extension d'EventDispatcher. Dans ActionScript 3.0, la plupart des classes nécessitant l'utilisation d'EventDispatcher telles que MovieClip et autres DisplayObject sont des extensions de cette classe, ce qui permet un accès et une utilisation facilités. Les utilisateurs expérimentés ont toutefois la possibilité d'inclure la fonctionnalité EventDispatcher par composition, si besoin est.
Vous trouverez ci-dessous un récapitulatif des méthodes de la classe EventDispatcher dans ActionScript 3.0. Nombre de ces méthodes sont semblables à celles de la version précédente du langage :
addEventListener type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false :voidremoveEventListener type:String, listener:Function, useCapture:Boolean = false :voiddispatchEvent event:Event :BooleanhasEventListener type:String :BooleanwillTrigger type:String :BooleanSi vous utilisiez déjà ActionScript 2.0, vous remarquerez que deux méthodes ont été ajoutées : hasEventListener et willTrigger. De plus, dans ActionScript 3.0, addEventListener n'autorise que l'utilisation de fonctions comme écouteurs d'événement, contrairement à l'ancienne version qui permettait également l'utilisation d'objets. Dans la mesure où les méthodes sont désormais liées à leurs instances dans ActionScript 3.0, vous n'avez plus besoin d'utiliser des objets comme écouteurs. Le mot-clé this des fonctions référence automatiquement l'instance correspondante. En outre, la classe Delegate d'ActionScript 2.0 est désormais superflue.
addEventListener. Pour supprimer le gestionnaire approprié, les trois premiers arguments utilisés dans addEventListener doivent être repris avec removeEventListener.hasEventListener, à la différence qu'elle vérifie l'objet en cours ainsi que tous les objets susceptibles d'être affectés par la propagation de l'événement.Ces méthodes, ainsi que toute autre fonction ou méthode d'ActionScript 3.0, sont également décrites dans le guide de Référence du langage et des composants ActionScript 3.0.
Prenons un exemple simple : vous cliquez sur une instance carrée dont le nom est « box » cadre à l'écran voir Figure 1 . Dans cet exemple, l'objectif est de gérer cet événement de sorte que le texte « click » s'affiche dans le panneau de sortie lorsque vous cliquez dans le cadre à l'aide de la souris.
Pour créer cette animation test, procédez comme suit :
function clickHandler(event:MouseEvent):void {
trace("click");
}
box.addEventListener(MouseEvent.CLICK, clickHandler);
<?xml version="1.0" encoding="utf-8"?>
"mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
applicationComplete="initApp()""
<mx:Script>
"![CDATA[
public function clickHandler(event:MouseEvent):void {
trace("click");
}
public function initApp():void {
box.addEventListener(MouseEvent.CLICK, clickHandler);
}
]]"
</mx:Script>
<mx:Canvas id="box" width="200" height="200" backgroundColor="#800000">
</mx:Canvas>
</mx:Application>
Examinons le script. La première étape consiste à définir le gestionnaire d'événements (fonction d'écouteur). Comme pour tous les événements, une seule instance d'événement automatiquement transférée à la fonction lorsque le distributeur d'événements l'appelle est acceptée dans la liste des paramètres. La fonction est ensuite définie comme écouteur de l'instance de cadre (distributeur d'événements) écoutant les événements MouseEvent.CLICK à l'aide d'un appel addEventListener de base (dans Flex, cela se produit dans la méthode initApp). Dans la mesure où le cadre est une instance de MovieClip (Canvas dans Flex), il hérite de la classe EventDispatcher et a accès à toutes les méthodes associées, y compris addEventListener.
MouseEvent.CLICK est une variable constante définie dans la classe MouseEvent. Elle fournit la chaîne correspondant à l'événement. Pour MouseEvent.CLICK, il s'agit de « click ». D'autres types d'événements sont stockés dans des constantes semblables dans la classe MouseEvent, ainsi que d'autres classes relatives aux événements. Notez qu'un grand nombre de ces événements ont changé entre les version 2.0 et 3.0 d'ActionScript. Par exemple, dans ActionScript 3.0, l'événement MouseEvent.MOUSE_DOWN (ou « mouseDown ») est utilisé au lieu de l'événement onPress d'ActionScript 2.0. Pour découvrir d'autres distinctions, examinez le package Event et ses différentes classes dans le document Informations de référence sur le langage ActionScript 3.0.
Dans cet exemple, vous auriez pu utiliser « click » au lieu de MouseEvent.CLICK, mais l'utilisation de ces constantes permet de détecter les coquilles dans le code. Si une faute s'était glissée lors de la saisie de la chaîne « click », aucune erreur n'aurait été renvoyée au moment de la compilation car, dans la mesure où il s'agit d'une chaîne, Flash ne peut pas déterminer si son contenu est exact. En revanche, si vous avez mal orthographié MouseEvent.CLICK, Flash est capable de le détecter et de renvoyer une erreur au moment de la compilation. La plupart des classes d'événements disposent de constantes liées aux chaînes correspondant à leur type d'événement. Il est fortement conseillé de les utiliser plutôt que de saisir la chaîne elle-même.
Si vous testez l'animation, vous constaterez que le mot « click » apparaît lorsque vous cliquez sur le cadre qui s'affiche.
Remarque : Les utilisateurs de Flex doivent veiller à tester l'animation à l'aide de Debug afin que la trace d'exécution puisse être capturée par Flex Builder.
Bien que vous ne l'ayez peut-être pas remarqué dans l'exemple précédent, outre l'objet sur lequel vous avez cliqué, l'événement résultant du clic dans le cadre affecte divers objets. La principale nouvelle fonctionnalité d'ActionScript 3.0 en matière de gestion d'événements est la propagation : le transfert d'un événement unique à plusieurs objets. Dans le cadre d'une propagation d'événements, l'objet d'origine de l'événement n'est pas le seul à recevoir l'événement.
Dans ActionScript 2.0, la propagation d'événements n'existait pas. Vous ne pouviez pas utiliser, dans un objet disposant de son propre gestionnaire d'événements, d'autres objets auxquels des gestionnaires d'événements étaient associés. À titre d'exemple, dans ActionScript 2.0, si vous attribuez un gestionnaire d'événements onPress à un objet fenêtre contenant un bouton auquel des gestionnaires d'événements onPress (ou semblables) sont associés, ces derniers ne fonctionnent pas ; ils ne reçoivent pas les événements. Ce problème a été résolu dans ActionScript 3.0. Vous pouvez désormais propager les événements à travers les instances et leurs parents.
Lors de la propagation, l'événement peut se trouver dans trois « phases » (voir Figure 2). Chaque phase représente un chemin ou l'emplacement d'un événement alors qu'il est transféré aux différents objets d'affichage qui lui sont liés dans Flash. Ces trois phases sont :
Cependant, tous les événements ne peuvent pas être propagés et tous les événements propagés ne passent pas nécessairement par chaque phase. Par exemple, si l'objet scène (stage) reçoit un événement, seule une phase cible aura lieu car aucun objet parent n'existe pour les phases de capture et de remontée.
Remarque : Dans Flex, la hiérarchie est légèrement différente car elle contient l'instance Application entre la racine (root) et l'instance Canvas du cadre (non comprise dans l'illustration).
Au cours de sa propagation, l'événement appelle toutes les fonctions d'écouteurs que vous avez ajoutées pour cet événement. Ainsi, lorsque vous cliquez dans le cadre, l'événement n'est pas limité à ce dernier ; la scène le reçoit également. Elle le reçoit à deux reprises : une fois lors de la phase de capture et une fois lors de la phase de remontée (voir Figure 3).
Ajoutez des écouteurs à cet exemple afin de mieux comprendre le fonctionnement.
Pour visualiser la propagation d'un clic de souris à travers plusieurs objets de la hiérarchie de la liste d'affichage, vous pouvez ajouter des écouteurs de façon à ce que chaque objet concerné reçoive l'événement. Dans le cadre de cet exemple, des écouteurs seront utilisés pour toutes les phases de l'événement. Pour ce faire, le troisième paramètre d'addEventListener, useCapture, est nécessaire.
Le paramètre useCapture d'addEventListener permet de spécifier si un écouteur doit être actif lors de la phase de capture. Si ce n'est pas le cas, il écoutera l'événement uniquement au cours des deux autres phases. Par défaut, la valeur est définie sur false et l'écouteur n'est actif que dans la phase cible et la phase de remontée. Si vous définissez le paramètre sur true, l'écoute aura également lieu lors de la phase de capture. Si vous souhaitez qu'un événement soit écouté au cours de toutes les phases, utilisez addEventListener à deux reprises : une fois en définissant useCapture sur false (ou omis) et une fois en définissant useCapture sur true.
Dans cet exemple (Figure 4), nous allons ajouter des écouteurs pour la scène (stage), la racine (root) et le cadre (box). Pour stage et root, nous alternerons entre l'utilisation et la non-utilisation du paramètre useCapture.
function boxClick(event:MouseEvent):void {
trace("box click");
}
function rootClick(event:MouseEvent):void {
trace("root click");
}
function stageClick(event:MouseEvent):void {
trace("stage click");
}
box.addEventListener(MouseEvent.CLICK, boxClick);
root.addEventListener(MouseEvent.CLICK, rootClick);
root.addEventListener(MouseEvent.CLICK, rootClick, true);
stage.addEventListener(MouseEvent.CLICK, stageClick);
stage.addEventListener(MouseEvent.CLICK, stageClick, true);
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
applicationComplete="initApp()">
<mx:Script>
<![CDATA[
public function boxClick(event:MouseEvent):void {
trace("box click");
}
public function rootClick(event:MouseEvent):void {
trace("root click");
}
public function stageClick(event:MouseEvent):void {
trace("stage click");
}
public function initApp():void {
box.addEventListener(MouseEvent.CLICK, boxClick);
root.addEventListener(MouseEvent.CLICK, rootClick);
root.addEventListener(MouseEvent.CLICK, rootClick, true);
stage.addEventListener(MouseEvent.CLICK, stageClick);
stage.addEventListener(MouseEvent.CLICK, stageClick, true);
}
]]>
</mx:Script>
<mx:Canvas id="box" width="200" height="200" backgroundColor="#800000">
</mx:Canvas>
</mx:Application>
Remarque : Veillez à utiliser l'événement applicationComplete dans Flex afin de garantir l'accès à stage et root au sein du script Application. L'accès à stage et root est impossible dans l'événement creationComplete.
Cliquez sur l'animation pour la tester. Vous devriez obtenir la sortie suivante :
stage click
root click
box click
root click
stage click
Vous pouvez constater que les objets scène et racine ont reçu l'événement à deux reprises : une fois lors de la phase de capture et une fois lors de la phase de remontée. L'objet cible de l'événement (le cadre) n'a quant à lui reçu l'événement qu'une seule fois lors de la phase cible. Cliquez en dehors du cadre (sur la scène). Si vous utilisez Flash, vous obtenez le résultat suivant :
stage click
Dans la mesure où l'objet scène se trouve au sommet de la hiérarchie de l'animation Flash, la seule phase d'un événement relatif à la scène est la phase cible.
Dans Flex, vous obtenez un résultat semblable à celui-ci lorsque vous cliquez sur la scène :
stage click
root click
root click
stage click
Cela est dû à l'instance d'application intermédiaire Application.application qui contient l'arrière-plan en dégradé recouvrant l'ensemble de la scène. Lorsque vous cliquez sur la scène, vous cliquez sur cette instance (pour laquelle aucun écouteur n'est défini) et non sur la scène en soi. Si aucune instance d'application intermédiaire n'est présente, seul l'écouteur de la scène est appelé.
Bien que la propagation d'événements s'applique essentiellement aux événements de souris, d'autres événements tels que les événements de clavier peuvent être concernés. Vous pouvez également l'utiliser dans le cadre des événements d'ajout et de suppression dans les instances DisplayObjectContainer, pour ajouter ou supprimer les objets enfant des listes d'affichage.
Dans Flash, la gestion de tous les événements, tels que les clics de souris, commence par le ciblage de ces événements. Cette étape permet de déterminer l'objet cible de l'événement (celui dont il provient) dans Flash. Dans les exemples précédents, nous avons vu comment il était possible de détecter un clic dans un cadre ou sur la scène dans Flash. Un seul objet est référencé pour chaque événement de souris : l'objet capable de recevoir l'événement placé le plus haut dans la hiérarchie (voir Figure 5).
Ce comportement est quasi-identique à celui observé dans la version précédente du langage. Par exemple, dans ActionScript 2.0, si vous cliquez une fois sur deux boutons placés directement l'un au dessus de l'autre (en supposant que des gestionnaires d'événements y soient associés), seul le bouton placé au-dessus reçoit l'événement. Dans ActionScript 3.0, cela est toujours le cas. Bien que les deux boutons se trouvent techniquement en dessous de la souris lorsque vous cliquez dessus, seul le bouton placé au dessus reçoit l'événement car il s'agit de l'objet cible de l'événement.
Une différence est cependant à noter avec ActionScript 3.0 : par défaut, tous les objets d'affichage peuvent recevoir des événements de souris. Ainsi, même si aucun gestionnaire d'événements ne lui est associé, un objet d'affichage constitue une cible pour l'événement lorsque vous cliquez dessus ; les objets situés en dessous ne peuvent donc pas recevoir d'événements. Ce n'est pas le cas avec ActionScript 2.0. En effet, seules les instances de clip auxquelles vous avez associé un gestionnaire d'événements tel que onPress peuvent recevoir des événements dans ActionScript 2.0. Si aucun gestionnaire d'événements n'est spécifié pour ces instances, ce sont celles qui se trouvent en dessous qui sont ciblées.
Pour reproduire ce comportement dans ActionScript 3.0, utilisez la propriété InteractiveObject mouseEnabled. Si vous la définissez sur false, l'instance d'objet interactif ne peut pas recevoir d'événements de souris, mais les instances situées en dessous peuvent être ciblées :
myInteractiveObject.mouseEnabled = false;
Les objets événement sont les objets que les fonctions d'écouteurs reçoivent sous forme d'argument lorsqu'elles sont appelées dans le cadre d'un événement. Les objets événement utilisés dans ActionScript 3.0 sont semblables à ceux utilisés dans la version ActionScript 2.0 de la classe EventDispatcher. Ils sont toutefois plus structurés (ils disposent de leur propre classe : la classe Event) et des propriétés ont été ajoutées pour décrire l'événement géré.
Les objets événement que les fonctions d'écouteurs reçoivent sont toujours de type Event mais peuvent également être des sous-classes d'Event plutôt que des instances d'Event. MouseEvent et KeyboardEvent sont des sous-classes couramment utilisées pour les événements relatifs à la souris et au clavier, respectivement. Chaque classe contient également les constantes de type d'événement utilisées pour écouter les événements liés, par exemple MouseEvent.CLICK.
Dans ActionScript 3.0, la scène est un nouveau concept, tout du moins en termes d'objet référençable dans le code. Il s'agit du conteneur situé au sommet de la hiérarchie des objets d'affichage d'une animation Flash. Il équivaut presque à _root dans ActionScript 2.0. Dans ActionScript 3.0, la racine (accessible via la propriété root de DisplayObject, sans trait de soulignement) est désormais intégrée à l'objet scène.
De plus, pour les événements de souris, le ciblage de la scène ne dépend pas de son contenu, contrairement à d'autres objets. Dans l'exemple du cadre, la hiérarchie de base est : scène > racine > cadre. Dans Flex, cette hiérarchie est la suivante : scène > racine > application > cadre. Pour que le cadre sur lequel vous cliquez soit la cible de l'événement clic dans Flash, vous devez cliquer sur sa forme. De même, pour cliquer sur l'objet racine, vous devez cliquer sur son contenu ou sur l'instance du cadre. Si vous cliquez à un autre endroit, vous ne cliquerez pas sur l'objet racine car il est uniquement constitué du cadre. Pour cliquer sur la scène, vous pouvez toutefois cliquer n'importe où dans l'animation car elle constitue l'arrière-plan permanent de l'animation, même en l'absence d'autre contenu. Dans certains cas (par exemple, avec des événements de souris relâchée et de souris déplacée), la scène détecte même les interactions hors de l'animation. Ce comportement est important car, comme nous allons le voir, il permet d'effectuer certaines tâches dans ActionScript 3.0.
Voici un récapitulatif rapide des propriétés d'événement courantes :
type:StringeventPhase:uintbubbles:Booleancancelable:Booleantarget:ObjectcurrentTarget:ObjectDes propriétés supplémentaires s'appliquent aux sous-classes. Par exemple, la propriété relatedObject, qui décrit un objet d'affichage lié à l'événement en cours (comme l'objet duquel vous êtes parti pour déplacer la souris et déclencher l'événement en cours), existe également pour les instances MouseEvent.
Certaines propriétés devraient donc vous paraître familières. Vous trouverez ci-dessous une description des propriétés mentionnées plus haut :
addEventListener. Ex. : MouseEvent.CLICK.EventPhase.CAPTURING_PHASE, EventPhase.AT_TARGET et EventPhase.BUBBLING_PHASE selon la phase dans laquelle l'écouteur a été appelé.TextEvent.TEXT_INPUT) peut détecter le moment où cette action se produit et annuler le comportement par défaut. Dans ce cas, la propriété cancelable est définie sur true.Ces propriétés sont utiles lorsque vous déterminez les actions à entreprendre suite à certains événements.
L'un des inconvénients d'ActionScript 3.0 est l'absence d'un événement équivalent au onReleaseOutside d'ActionScript 2.0. Des événements de souris enfoncée et relâchée existent pour ActionScript 3.0, mais aucun événement n'existe pour le déclenchement d'un événement en dehors de l'objet sur lequel vous avez cliqué. Pour détecter l'action qui consiste à cliquer sur un objet à l'aide de la souris puis relâcher le bouton de cette dernière en dehors de cet objet, vous devez faire preuve d'imagination en exploitant le comportement unique de la scène.
Voici quelques approches à adopter pour y parvenir. La méthode la plus simple est la suivante :
target de l'objet événement. Si tel est le cas, la souris a été relâchée sur l'objet cible d'origine. Dans le cas contraire, elle a été relâchée en dehors de cet objet.Dans la mesure où la scène capture tous les événements de souris, elle recevra inévitablement tous les événements de souris relâchée. En ajoutant un écouteur de souris relâchée pour la scène dans l'écouteur de souris enfoncée de l'objet cible, vous saurez si le prochain relâchement de la souris a lieu sur l'objet d'origine du clic ou en dehors de cet objet (événement de souris relâchée en dehors de l'objet).
function boxDown(event:MouseEvent):void {
trace("box down");
stage.addEventListener(MouseEvent.MOUSE_UP, boxUpOutside);
}
function boxUpOutside(event:MouseEvent):void {
if (event.target != box) {
trace("box up outside");
}
stage.removeEventListener(MouseEvent.MOUSE_UP, boxUpOutside);
}
box.addEventListener(MouseEvent.MOUSE_DOWN, boxDown);
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
applicationComplete="initApp()">
<mx:Script>
<![CDATA[
public function boxDown(event:MouseEvent):void {
trace("box down");
stage.addEventListener(MouseEvent.MOUSE_UP, boxUpOutside);
}
public function boxUpOutside(event:MouseEvent):void {
if (event.target != box) {
trace("box up outside");
}
stage.removeEventListener(MouseEvent.MOUSE_UP, boxUpOutside);
}
public function initApp():void {
box.addEventListener(MouseEvent.MOUSE_DOWN, boxDown);
}
]]>
</mx:Script>
<mx:Canvas id="box" width="200" height="200" backgroundColor="#800000">
</mx:Canvas>
</mx:Application>
Testez l'animation en cliquant dans le cadre. Essayez de cliquer puis relâcher la souris lorsque le curseur se trouve dans le cadre. Ensuite, cliquez et faites glisser le curseur de la souris en dehors du cadre, puis relâchez le bouton de la souris. Lorsque vous cliquez dans le cadre, une sortie « box down » est générée. Lorsque vous cliquez dans le cadre et que vous relâchez le bouton de la souris alors que le curseur se trouve en dehors de ce cadre, une sortie « box down » et « box up outside » est générée, et ce, même si le curseur se trouve en dehors de la fenêtre de Flash Player (ceci est spécifique aux événements de souris relâchée associés à la scène).
Plusieurs méthodes utiles sont également associées aux objets événement. Voici quelques-unes de ces méthodes :
stopPropagation()stopImmediatePropagation()preventDefault()isDefaultPrevented()Comme pour les propriétés, les sous-classes Event contiennent souvent des méthodes supplémentaires. Par exemple, les instances KeyboardEvent et MouseEvent disposent également d'une méthode updateAfterEvent(). Cette méthode est utilisée pour redessiner l'écran à la fin de l'événement.
Vous trouverez ci-dessous une description des actions que certaines de ces méthodes d'événement permettent d'effectuer :
stopPropagation, à une exception : la méthode stopPropagation n'empêchera pas d'autres événements d'être appelés dans l'objet en cours (si plusieurs écouteurs sont définis pour le même événement dans cet objet).
true ou false, suivant que la méthode preventDefault a été appelée ou non pour l'événement en cours (au sein de l'écouteur en cours ou d'un écouteur précédent appelé en réponse à cet événement).Comme indiqué plus haut, dans ActionScript 3.0, les événements de souris sont activés pour tous les objets interactifs par nature. Vous pouvez désactiver l'interaction de la souris en définissant la propriété mouseEnabled sur false. Une propriété semblable existe avec les conteneurs d'objets d'affichage pour désactiver les événements de souris pour tous les enfants de l'objet. Il s'agit de mouseChildren. Si vous définissez la propriété mouseChildren sur false, vous pouvez empêcher l'activation de la souris pour l'ensemble des instances d'un conteneur d'objets d'affichage.
Toutefois, si vous souhaitez seulement désactiver certains événements de souris pour un groupe d'objets au sein d'un conteneur, vous devez opter pour une approche différente. Dans ce cas, utilisez un écouteur d'événement dans l'instance parent cible qui, lorsqu'il aura détecté la désactivation de l'événement, arrêtera sa propagation. Cela permet d'éviter aux écouteurs utilisés pour des objets au sein du conteneur d'être appelés.
Dans l'exemple suivant, nous allons créer deux boutons dans une fenêtre conteneur. L'activation et la désactivation des clics correspondants seront définies à partir d'un autre bouton situé en dehors du conteneur. Une propriété de ce troisième bouton externe déterminera si le conteneur arrête ou non la propagation de l'événement de clic lorsqu'il est détecté lors de sa phase de capture.
var clickEnabled:Boolean = true;
function clickHandler(event:MouseEvent):void {
trace("click: " + event.currentTarget.name);
}
function toggleEnabled(event:MouseEvent):void {
clickEnabled = !clickEnabled;
}
function disableClickHandler(event:MouseEvent):void {
if (clickEnabled == false) {
event.stopPropagation();
}
}
window.button1.addEventListener(MouseEvent.CLICK, clickHandler);
window.button2.addEventListener(MouseEvent.CLICK, clickHandler);
window.addEventListener(MouseEvent.CLICK, disableClickHandler, true);
enabler.addEventListener(MouseEvent.CLICK, toggleEnabled);
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
applicationComplete="initApp()">
<mx:Script>
<![CDATA[
public var clickEnabled:Boolean = true;
public function clickHandler(event:MouseEvent):void {
trace("click: " + event.currentTarget.name);
}
public function toggleEnabled(event:MouseEvent):void {
clickEnabled = !clickEnabled;
}
public function disableClickHandler(event:MouseEvent):void {
if (clickEnabled == false) {
event.stopPropagation();
}
}
public function initApp():void {
button1.addEventListener(MouseEvent.CLICK, clickHandler);
button2.addEventListener(MouseEvent.CLICK, clickHandler);
container.addEventListener(MouseEvent.CLICK, disableClickHandler, true);
enabler.addEventListener(MouseEvent.CLICK, toggleEnabled);
}
]]>
</mx:Script>
<mx:Panel width="250" height="250" layout="absolute" id="window">
<mx:Button x="30" y="25" label="Button" id="button1"/>
<mx:Button x="30" y="55" label="Button" id="button2"/>
</mx:Panel>
<mx:Button label="Enabler" id="enabler"/>
</mx:Application>
Testez l'animation afin de voir comment la variable clickEnabled est utilisée avec le bouton Enabler pour désactiver ou activer la réception de l'événement de clic par les boutons du conteneur. Dans la mesure où la variable clickEnabled désactive uniquement les événements de clic, les autres événements de souris, tels que le placement du curseur sur un élément, continuent de fonctionner pour les boutons inclus dans la fenêtre. Ce type d'événement est cependant désactivé si vous définissez la propriété mouseChildren sur false pour le conteneur.
Dans ActionScript 3.0, EventDispatcher permet de capturer des événements. Vous pouvez également l'utiliser pour créer vos propres événements. Plusieurs possibilités s'offrent à vous : distribuer des événements nouveaux ou existants, créer de nouveaux types d'événements et définir de nouvelles classes d'événement (basées sur la classe Event) dont les instances sont transférées à des gestionnaires d'événements qui écoutent l'événement.
Pour distribuer des événements manuellement, utilisez la méthode dispatchEvent d'EventDispatcher. Lorsque vous appelez cette méthode, vous transférez un objet événement décrivant l'événement distribué. L'événement se déplace ensuite parmi toutes les cibles valides (multiples dans le cas d'une propagation), ce qui entraîne l'appel des gestionnaires d'événements chargés d'écouter ces cibles (s'ils écoutent ce type d'événement spécifique). Lorsqu'ils sont appelés, les gestionnaires reçoivent l'objet événement transféré à dispatchEvent :
target.dispatchEvent(new Event("type"));
De nouvelles instances d'événement sont créées, pour lesquelles un paramètre de type et des paramètres d'annulation et de remontée optionnels sont définis. Par défaut, tout du moins dans la classe Event, les paramètres de remontée et d'annulation sont définis sur false. Certaines sous-classes de la classe Event telles que MouseEvent acceptent même des paramètres supplémentaires. Pour la classe MouseEvent, le paramètre de remontée est défini sur true par défaut. Pour plus d'informations sur l'utilisation de la sous-classe MouseEvent et d'autres classes Event, consultez le guide de Référence du langage et des composants ActionScript 3.0.
Vous pouvez créer vos propres classes d'événement en étendant la classe Event. Cela vous permet de distribuer ensuite vos propres événements personnalisés et de définir les propriétés que vous souhaitez pour ces sous-classes. Si vous étendez la classe Event, veillez toutefois à remplacer la méthode par défaut et implémenter votre propre méthode clone . Bien que la méthode de clonage ne soit pas nécessaire dans tous les cas, elle permet parfois de copier des instances d'événement en interne dans Flash. Si la méthode de clonage ne crée pas une copie exacte de l'instance d'événement concernée, une erreur se produit.
Les événements personnalisés sont utiles car ils permettent d'indiquer des événements qui ne sont pas reconnus dans Flash Player de façon inhérente. Si vous créez vos propres classes Event, vous pouvez associer des gestionnaires aux événements personnalisés en spécifiant des informations supplémentaires à leur sujet. Dans l'exemple suivant, nous utiliserons une classe personnalisée BounceEvent avec un événement de rebond pour indiquer qu'un cadre a rebondi sur le bord de l'écran.
À l'instar des classes d'ActionScript 2.0, la classe BounceEvent sera définie dans un fichier ActionScript externe. Outre les propriétés d'événement habituelles automatiquement héritées de la classe Event, la classe BounceEvent comprend une propriété side supplémentaire permettant à l'utilisateur de déterminer de quel côté de l'écran provient l'objet rebondissant.
Il est également conseillé de spécifier des constantes de type par ex., MouseEvent.MOUSE_DOWN en plus des propriétés personnalisées dans les classes d'événements personnalisés, en s'assurant que ces constantes correspondent aux différents types utilisés avec l'événement. Un type d'événement « bounce » stocké dans la constante BOUNCE est utilisé par la classe BounceEvent, dont la définition est la suivante :
package {
import flash.events.Event;
public class BounceEvent extends Event {
public static const BOUNCE:String = "bounce";
private var _side:String = "none";
public function get side():String {
return _side;
}
public function BounceEvent(type:String, side:String){
super(type, true);
_side = side;
}
public override function clone():Event {
return new BounceEvent(type, _side);
}
}
}
Vous remarquerez qu'une fonction de clonage a également été incluse dans la définition de la classe BounceEvent. Bien que la valeur de retour corresponde à une instance BounceEvent et non à une instance Event, il est possible d'inclure cette fonction car la classe BounceEvent est une extension d'Event et qu'elle hérite donc de son type. La valeur de retour de la fonction de clonage doit être de type Event dans la mesure où les opérations de remplacement doivent disposer de la même signature de fonction que les méthodes d'origine qu'elles remplacent.
Vous pouvez désormais utiliser cette classe pour créer des instances d'événement à distribuer lorsqu'un cadre rebondit. Les gestionnaires d'événements écoutant le rebond peuvent recevoir les instances BounceEvent liées à cet événement.
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
var velocityX:Number = 5;
var velocityY:Number = 7;
var padding:Number = 10;
function bounceHandler(event:BounceEvent):void {
trace("Bounce on " + event.side + " side");
}
function moveBox(event:Event):void {
box.x += velocityX;
box.y += velocityY;
var limitLeft:Number = padding;
var limitRight:Number = stage.stageWidth - box.width - padding;
var limitTop:Number = padding;
var limitBottom:Number = stage.stageHeight - box.height - padding;
if (box.x <= limitLeft) {
velocityX = Math.abs(velocityX);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "left"));
}else if (box.x >= limitRight){
velocityX = -Math.abs(velocityX);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "right"));
}
if (box.y <= limitTop) {
velocityY = Math.abs(velocityY);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "top"));
}else if (box.y >= limitBottom){
velocityY = -Math.abs(velocityY);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "bottom"));
}
}
box.addEventListener(Event.ENTER_FRAME, moveBox);
addEventListener(BounceEvent.BOUNCE, bounceHandler);
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" width="300" height="300"
applicationComplete="initApp()">
<mx:Script>
<![CDATA[
public var velocityX:Number = 5;
public var velocityY:Number = 7;
public var padding:Number = 10;
public function bounceHandler(event:BounceEvent):void {
trace("Bounce on " + event.side + " side");
}
public function moveBox(event:Event):void {
box.x += velocityX;
box.y += velocityY;
var limitLeft:Number = padding;
var limitRight:Number = stage.stageWidth - box.width - padding;
var limitTop:Number = padding;
var limitBottom:Number = stage.stageHeight - box.height - padding;
if (box.x <= limitLeft) {
velocityX = Math.abs(velocityX);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "left"));
}else if (box.x >= limitRight){
velocityX = -Math.abs(velocityX);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "right"));
}
if (box.y <= limitTop) {
velocityY = Math.abs(velocityY);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "top"));
}else if (box.y >= limitBottom){
velocityY = -Math.abs(velocityY);
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "bottom"));
}
}
public function initApp():void {
box.addEventListener(Event.ENTER_FRAME, moveBox);
addEventListener(BounceEvent.BOUNCE, bounceHandler);
}
]]>
</mx:Script>
<mx:Canvas width="20" height="20" x="20" y="20" backgroundColor="#800000" id="box">
</mx:Canvas>
</mx:Application>
Testez l'animation. Lorsque le cadre rebondit sur les côtés de la scène, la sortie suivante est générée :
Bounce on bottom side
Bounce on right side
Bounce on top side
Bounce on left side
Bounce on bottom side
...
Elle résulte de l'appel de la fonction de gestionnaire d'événements bounceHandler à chaque événement de rebond. L'événement de rebond est distribué au sein de la fonction moveBox (gestionnaire d'événements pour enterframe) à chaque fois qu'une autre direction est attribuée à l'instance du cadre à l'aide de la méthode dispatchEvent. Par exemple, examinons la ligne de code suivante :
box.dispatchEvent(new BounceEvent(BounceEvent.BOUNCE, "left"));
Elle permet de distribuer un nouvel événement de rebond à partir de l'instance de cadre vers tous les écouteurs capables de déterminer que le rebond est du côté gauche à l'aide de la propriété side personnalisée provenant de l'objet événement.
Vous remarquerez peut-être que, bien que l'événement ait été distribué à partir du cadre, la fonction bounceHandler (qui ne constituait pas un écouteur de l'instance de cadre) a pu recevoir l'événement. Cela est dû au fait que, dans la définition de BounceEvent, un second argument true a été attribué à l'appel de super() dans le constructeur (qui exécute le constructeur Event), indiquant ainsi que l'événement remonte. Ainsi, lors de la propagation, l'événement a pu être transféré à tous les parents du cadre, y compris celui au sein duquel bounceHandler écoutait (racine dans Flash, application dans Flex).
Si vous commencez tout juste à utiliser ActionScript 3.0 ou que vous êtes habitué aux événements d'ActionScript 2.0, il vous faudra peut-être un peu de temps pour vous familiariser avec les comportements du nouveau système d'événements. Passé ce stade, vous serez en mesure d'apprécier pleinement le niveau de contrôle qu'il offre. Voici quelques conseils et précautions à observer lorsque vous utilisez des événements dans ActionScript 3.0 :
eventPhase de l'objet événement permet d'obtenir des informations utiles et d'éviter toute propagation d'événements indésirable. Si cette propriété correspond à EventPhase.AT_TARGET, vous pouvez déterminer la cible de l'événement.MouseEvent.ROLL_OVER et MouseEvent.ROLL_OUT, et d'autre part, MouseEvent.MOUSE_OVER et MouseEvent.MOUSE_OUT. La différence réside dans le fait que les événements de survol ne remontent pas. Il n'y aura donc aucune confusion avec les événements de survol et de sortie propagés à partir des enfants d'un objet. Pour les autres événements, vous pouvez utiliser la propriété mouseChildren pour éviter les conflits de propagation concernant les événements de souris.mouseEnabled de l'objet sur false.stage est uniquement accessible à partir des objets d'affichage lorsqu'ils figurent dans une liste d'affichage active, ou plutôt une liste d'affichage rattachée à la scène et visible à l'écran. Si un objet d'affichage ne figure pas dans cette liste, sa propriété stage est nulle. Le comportement est le même pour la propriété root.Event.ADDED et Event.REMOVED remontent comme les événements de souris, n'oubliez pas que les phases de capture et de remontée ne concernent que les parents. Les enfants d'une instance ne reçoivent pas les événements du parent. Pour les enfants d'un conteneur, il est donc difficile de savoir si le conteneur ou l'un de ses parents a été ajouté à une liste d'affichage active et, par là-même, si les propriétés stage et root de DisplayObject sont accessibles. Pour résoudre ce problème, utilisez les événements Event.ADDED_TO_STAGE et Event.REMOVED_FROM_STAGE ajoutés dans la version 9,0,28,0 de Flash Player sortie le 14 novembre 2006 . Ces événements permettent aux objets d'affichage de savoir s'ils ont été ajoutés ou retirés d'une liste d'affichage active et donc si les propriétés stage et root sont accessibles.MouseEvent.MOUSE_MOVE est uniquement invoqué lorsque le curseur de la souris se trouve au-dessus de l'objet récepteur de l'événement. Si vous utilisez cet événement pour déplacer ou faire glisser des objets à l'écran, il est possible que vous le perdiez si vous placez le curseur de la souris en dehors de la zone de l'objet par inadvertance. Pour résoudre ce problème, ajoutez des écouteurs à la scène.stopImmediatePropagation , indiquez qu'il est prioritaire à l'aide du quatrième paramètre dans addEventListener. Les écouteurs auxquels vous attribuez la priorité la plus élevée sont toujours appelés en premier.Lorsque vous apprenez de nouvelles stratégies de développement, il est utile de créer de petits fichiers test semblables aux exemples décrits dans ce didacticiel. Isolez la fonctionnalité et spécifiez différentes valeurs pour les paramètres afin de mieux comprendre le contrôle et la capture des événements dans ActionScript 3.0. Utilisez différents scénarios pour découvrir les différences qui existent avec ActionScript 2.0 en ce qui concerne la gestion d'événements. Vous pouvez, par exemple, placer des objets les uns au-dessus des autres. Les résultats affichés dans le panneau de sortie vous renseigneront immédiatement sur les événements reçus.
Une fois que vous vous êtes familiarisé avec le comportement de la nouvelle classe EventDispatcher, vous pouvez étendre la classe Event afin de créer vos propres classes personnalisées en les définissant dans un fichier ActionScript externe. Entraînez-vous à créer des sous-classes personnalisées afin de distribuer vos propres événements avec des propriétés uniques. Lorsque vous créez vos propres classes Event, vous pouvez utiliser les paramètres par défaut et fournir de nouveaux gestionnaires pour un événement personnalisé qui n'est pas encore géré dans Flash Player. Cette stratégie est particulièrement utile pour déterminer la position d'un objet par rapport à l'écran et permettre une interactivité utilisateur avancée. Une fois que vous maîtrisez l'utilisation des nouvelles fonctions de gestion d'événements disponibles dans ActionScript 3.0, de nombreuses possibilités de développement s'offrent à vous et vous bénéficiez d'un contrôle accru sur le suivi des entrées.
Veillez à télécharger et explorer les fichiers exemples fournis au début du didacticiel afin de passer en revue les concepts abordés ici. En outre, il est conseillé de se familiariser avec les classes relatives aux événements et les informations de gestion d'événements disponibles dans le guide de Référence du langage et des composants ActionScript 3.0.
ActionScript Blog |
More |
ActionScript Cookbook |
More |
| 01/20/2012 | Skinnable Transform Tool |
|---|---|
| 12/14/2011 | What is a "Hybrid Extension"? |
| 12/05/2011 | String replaceAll in ActionScript |
| 12/04/2011 | Flex: Validate/revert editable Datagrid input value |