13/01/2008 - 14:46
Sinds de komst van Adobe Flash CS3 en van Actionscript 3 is het Event gebeuren in flash aardig veranderd. Dit artikel beschrijft op duidelijke manier de werking van het nieuwe Event systeem in Actionscript 3.

Introductie Event systeem in Actionscript 3

Introductie Event systeem in Actionscript 3

Events

Simpel gezegd is een Event een gebeurtenis die tijdens het uitvoeren van het programma voorkomt. Een gebeurtenis waar je naar kan luisteren (middels Event Listeners), waardoor je kan reageren op het Event.

In Actionscript 3 is de Event architectuur gebaseerd op de W3C Document Object Model (DOM) Level 3 Events Specificatie, zie w3.org (Engels) voor meer informatie hierover.

Wanneer er in Actionscript 3 een Event plaatsvindt dan worden alle Event Listeners, die zich voor dat Event geregistreerd hebben, uitgevoerd. Een Event Listener is een functie of methode die zich registreert voor het Event. In code gesproken gaat dat zo:

addEventListener(MouseEvent.CLICK, clickListener);

Bovenstaande code zegt eigenlijk: Als er een muis klik plaatsvindt, voer dan de functie 'clickListener' uit.

Het Event Object

Bij de start van een Event maakt ActionScript een eventObject aan. In dit eventObject zit een representatie van het Event zelf. Het eventObject is altijd een instance van de Event class of daaruit voortgekomen classes.

Het eventObject wordt als referentie meegeven aan alle Listener functies/methodes die zich voor het Event hebben geregistreerd.
De gegevens die in het object staan bevatten altijd een 'type' en een 'target'.

De 'type' is de naam van het type Event (String in Actionscript), bijvoorbeeld 'click' voor een muis klik.

De 'target' is het Object waarop het Event plaatsvindt. Bij een muis klik is de 'target' bijvoorbeeld het Button object waarop je klikt. Andere voorbeeld o.a. een TextField waarin TextEvent's plaatsvinden zoals 'change' of 'textInput'.

In ActionScript zitten een groot aantal 'build-in' Events. Daarbij kan je denken aan MouseEvent's, KeyBoardEvent's en vele anderen.
Je kan op eenvoudige wijze Custom Event's maken echter dat gaat even buiten de scope van dit artikel.

Om te reageren op een Event moeten we weten wat voor een type event er plaatsvindt. Bijvoorbeeld een muis klik voor de build-in MouseEvent voor muis handelingen.

  • event type : flash.events.MouseEvent
  • event type eigenschap: MouseEvent.CLICK

Wanneer we nu wat willen doen in flash bij zo'n muis klik, dan registreren we er een listener voor.

Event Listeners

Wanneer je een listener registreert voor een Event word de methode die je opgeeft uitgevoerd. Laten we een listener registreren voor de eerder genoemde muis klik Event.

Bekijk onderstaande code:

function clickListener( e:MouseEvent):void
{
    trace("Muis geklikt event is: "+e);
}

De clickListener functie is klaar. Nu moeten we hem nog registreren voor het MouseEvent.CLICK event.

Een listener registreren gaat als volgt. Je kiest de target uit waar het event plaatsvindt, bijvoorbeeld je stage of een button instance 'but'.

Het eerste argument van addEventListener() is de naam van het Event type waarvoor je wilt registreren. Het tweede argument is de referentie naar de daadwerkelijke listener die je registreert.

but.addEventListener(MouseEvent.CLICK, clickListener);

Nu heeft de addEventListener() meer argumenten die je mee kan geven. De argumenten voor addEventListener() op een rij:

  1. type: (String) Het eerste argument in het voorbeeld de constante 'MouseEvent.CLICK' heeft als String waarde 'click'
  2. listener: (Object) De daadwerkelijke listener methode die je wilt registreren, 'clickListener' in het voorbeeld.
  3. useCapture: (Boolean) (standaard false)Registreer een listener's target parent (eerder in hiërarchie) voor de capture fase of de bubling fase. (zie fases verderop)
  4. priority: (int) (standaard 0) Stel de prioriteit van de listener. Standaard is de volgorde naar de volgorde van registreren. Hoe hoger hoe eerder en negatieve cijfers mogen ook. (Niet officieel in de (DOM) Level 3 Events Specificatie)
  5. useWeakReference: (Boolean) (standaard false) weakReference op true zorgt ervoor dat de listener uit het geheugen gaat wanneer er geen referentie meer naar bestaat. Het is wenselijk voor alle DisplayObjects de waarde standaard op true te zetten.

Terug naar het voorbeeld van het muis klik Event. De hele addEventListener() ziet er dan zo uit.

but.addEventListener(MouseEvent.CLICK, clickHandler, false, 0, true);

Event fases

Als een Event dispatched (plaatsvindt) kent het meerdere fases. Belangrijk is te weten welke fases dat zijn en hoe dat werkt in combinatie met het useCapture argument van addEventListener().

Om de volgorde te noemen maken we even een test opstelling.
Voor de rest van het artikel gaan we uit van een opstelling met een Sprite Object en een Button Object. Het Button object is aan de Sprite toegevoegd dus de Sprite is een parent van de Button.

De volgorde van een 'click' event:

  1. eventPhase 1 (Capture fase) Stage instance word gewaarschuwt
  2. eventPhase 1 (Capture fase) Sprite object word gewaarschuwt
  3. eventPhase 2 (Target fase) Button object word gewaarschuwt
  4. eventPhase 3 (Bubbling fase) Sprite object word gewaarschuwt
  5. eventPhase 3 (Bubbling fase) Stage instance word gewaarschuwt

Er zijn drie fases tijdens de Event uitvoering. Om een Listener goed te zetten is het van belang dat we het derde argument van de addEventListener(), de useCapture, de juiste waarde geven. Dit kan zijn true of false (standaard false).

In het voorbeeld is Sprite object een parent van het Button object. Stel we willen een listener registreren op de Sprite, die net als de button listener luistert naar MouseEvent.CLICK. Afhankelijk van de volgorde die je wilt, zet je de useCapture waarde.

useCapture

useCapture argument op true

We registreren een Listener voor het Sprite object, net als voor de Button voor het muis Klik Event (MouseEvent.CLICK), en we zetten het useCapture argument op true.

Door de useCapture op true registreer je de listener voor de capture fase. Hierdoor wordt de Sprite eerder gewaarschuwd dan de Button. De volgorde van het Event is dan immers capture fase: 'stage', 'sprite', target fase: 'button', bubling fase: 'sprite', bubling fase: 'stage'.
Laten we de trace() code eens bekijken. De code (kan in een lege FLA of vinden in het bijgevoegde voorbeeld bestand useCapture.fla).

//importeer de juiste classes
import fl.controls.Button;
import flash.display.*;
import flash.events.MouseEvent;
//maak de sprite
var sprite:Sprite = new Sprite();
sprite.x = 10;
sprite.y = 10;
//maak de button
var but:Button = new Button();
but.label = "Test";
but.width = 150;
but.height = 20;
but.move(20, 20);
//hang de button in de sprite
sprite.addChild(but);
//hang de sprite aan je movie
addChild(sprite);
//de button listener
function butListener( e:MouseEvent)
{
        trace("butListener :: eventFase = "+e.eventPhase);
}
//de sprite listener
function spriteListener( e:MouseEvent )
{
        trace("spriteListener :: eventFase = "+e.eventPhase);
}
//registeren van de listeners
but.addEventListener(MouseEvent.CLICK, butListener, false, 0, true);
sprite.addEventListener(MouseEvent.CLICK, spriteListener, true, 0, false);

Wanneer we deze code testen zien we de traces als volgt:

spriteListener :: eventFase = 1
butListener :: eventFase = 2

useCapture argument op false

Zet in de code de useCapture van de Sprite listener op false, om te zien dat de Sprite dan pas gewaarschuwd wordt in de 'bubbling fase'. De listener code vervangen of aanpassen zodat het er zo uit ziet:

//registeren van de listeners
but.addEventListener(MouseEvent.CLICK, butListener, false, 0, true);
sprite.addEventListener(MouseEvent.CLICK, spriteListener, false, 0, true);

De trace volgorde en de event fases worden nu anders. Nu word eerst de Button gewaarschuwd en daarna pas de sprite.

butListener :: eventFase = 2
spriteListener :: eventFase = 3

Listeners verwijderen

Zorg er, wanneer je listeners gebruikt, altijd voor dat je programma ook de listeners weer kan verwijderen. een listener verwijderen gaat heel simpel met onderstaande code:

sprite.removeEventListener(MouseEvent.CLICK, spriteListener);

Zorg dat niet gebruikte listeners verwijderd worden op bovenstaande manier. LET OP: Als je event bubling op true staat dan dien je die ook in de remove te zetten.
v.b.

jeObject.removeEventListener(MouseEvent.CLICK, jeListener, true);

Weak References

Voordat we het artikel afsluiten nog aanvullende informatie over de weakReference die je als 5e argument kan zetten.

WeakReferences kan je gebruiken bij het registreren van listeners en bij Dictonary's.
Het is goed gebruik om alle listeners die met DisplayObjects registreren te voorzien van de waarde true voor weakReference. Op die manier word de listener 'kan' de Garbage collector de listener opruimen.

Let op!: WeakReferences is niet bedoelt als listener weggooi automaat. Verwijder zelf altijd, niet langer gebruikte, listeners middels de eerder genoemde removeEventListener.

Tot zo ver dit artikel over Events in Adobe ActionScript 3.
Hopelijk geeft het je een inkijk in de werking van Events voor ActionScript 3 commentaar, suggesties, bugs graag melden.

Het voorbeeld bestand kan je hier downloaden

Goede tut, Folkert. Ik ben

Goede tut, Folkert. Ik ben eindelijk begonnen met AS3 [ik sla AS2 maar over denk ik]
groet,
Raween

He Folkert! Goed uitgebreid

He Folkert!

Goed uitgebreid artikel!
Ben flink bezig met AS3, en dit is een goede uitleg over het hele event systeem, thanks!

Groet Sidney