flash a_new_event_model

A new event model

In ActionScript 3 the event model has obviously evolved, the way in which the objects interact has been entirely revisited. The same principal of this event model is borrowed from a design model or design pattern called Observer which defines the interaction between multiple objects.

This design model can be defined in the following way:

The Observer design model defines a relation between one or many object types in a way that when an object changes state, all of those that depend upon it are notified and are automatically updated.

There are three keys elements to the Observer design model:

The target
We can consider the idea of an event as a change of state within a ‘target’. A click on a button or the end of data loading provoking the broadcast of an event by the target object. These events in ActionScript 3 are stored in the constant properties of classes linked to the environment.

The event
It is the source of the event that we call target because it is that which broadcasts events that can be heard by users or not. This target can be a button or a clip for example. Don’t worry, all of these events are documented, the documentation presents the broadcasted events for each object.

The listener
The listener should listen to any target event. It can be a function or a method. When the target changes state it broadcasts the appropriate event, if the listener is subscribed to a broadcasted event it is notified and executes an action. It is important to note that there can be multiple listeners for the same event, which is one of its strengths as shown here:

3.2.1.jpg

Our listeners are dependent of the target, they are subscribed. The target doesn’t know anything about listeners, it only knows if they are observed or not by its internal list of listeners. When one changes state, an event is broadcast, our listeners are notified and can of course react. All broadcasted events send information to the listeners allowing them to be kept up to date regarding modifications and therefore to be constantly up to date on the target.

We will discover throughout these articles the flexibility offered by this new event model and you will quickly appreciate its use.

It remains a relatively abstract concept so in order to change this let’s look at how the event model establishes itself within a traditional Flash application.

Let’s take a simple example made up of a button and a listening function reacting when the user clicks a button. In this case we have our three main elements of the new ActionScript 3 event model.

  • The target: the button
  • The event: the button click
  • The listener: the function

Placed into a traditional ActionScript 3 application we get the following diagram:

3.2.2.jpg

Our button is a target which can broadcast an event. This is listened to by a listener function.

Worth remembering

  • There is a single and unique event model in ActionScript 3.
  • This event model is based upon the Observer design model.
  • The three elements of this new event model are: the target, the event and the listener.
  • We can have as many listeners as we wish.
  • Many listeners can listen to the same event.

Everything is event based

The most important ingredient of the event model is the unique class called EventDispatcher. It is that which offers an object the possibility to broadcast events. All of the API objects on Flash 9 player inherit this class and possess the capacity to broadcast events. You probably remember all Flash classes are relative to the Flash player. Before Flash 9 player, these objects simply inherited the Object class, if we wanted to broadcast events we would have to implement the EventDispatcher class ourselves in these objects. In ActionScript 3 the EventDispatcher class is the basic class for all objects.

Here is the inheritance chain of the MovieClip class before Flash 9 player:

Object
|
+-MovieClip

In previous versions of Flash player the MovieClip class extended the Object class, if we wanted to broadcast events from a MovieClip we could implement a new event model ourselves. Let’s see how this has evolved with ActionScript 3 in Flash 9 player:

Object
|
+-EventDispatcher

The EventDispatcher class now inherits the Object class, all the other objects then inherit the EventDispatcher and benefit from native event broadcast. It is a massive evolution for ActionScript developers as most objects that we can manipulate have the possibility to broadcast events by default. The MovieClip class in Actionscript therefore firstly inherits the Object class then the EventDispatcher to then inherit different graphic classes. All the classes that reside in the Flash package follow this same principal. Here is the complete inheritance chain of the MovieClip class in ActionScript 3:

Object
|
+-EventDispatcher
|
+-DisplayObject
|
+-InteractiveObject
|
+-DisplayObjectContainer
|
+-Sprite
|
+-MovieClip

Let’s see how to use the new event model in different well known objects.

Listen to an event

When you want to keep up to date with the latest new releases from your video club you have many ways of doing it. The first is you going down to the shop to see the latest releases. This is a traditional approach which is not very optimized, we can imagine the number of visits that you would have to make before a new DVD interested you.

A second approach would be to leave a list of the films that you are waiting for with the manager of the video club and wait for him to call you when one of those films arrives. This is a much more effective approach for you and for the owner of the shop. He therefore becomes the broadcaster and you become the listener. He makes no decision for you, he is therefore the target, you are therefore the listener because you are subscribed to a specific event ‘the availability of a film that you are looking for’.

In ActionScript 3 the objects work in the same way. To obtain a notification when the user clicks on a button we subscribe to a listener linked to a event broadcasted by the target, our button in this case.

In order to listen to a specific event we use the addEventListener method. Here is its signature:

addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void

The first parameter takes the event to listen to, defined via a character string. The second parameter takes the listener as a reference which is subscribed to the event. The three last parameters will be explained later. Remember that only the objects in the Flash package use the event model. Let’s see how to listen to an event with a simple example.

Start a new Flash document and create a button symbol. Place an occurrence of this on the stage and call it MyButton.

On an AS layer add the following code:

myButton.addEventListener ( "click", clickButton );
function clickButton ( pEvt:MouseEvent ):void
{
// display : broadcasted event
trace("broadcasted event");
}

We put a reference to the listener function clickButton as a second parameter in the addEventListener method. Beware not to put double brackets when we change the reference to the function. The following code could not be compiled:

myButton.addEventListener( "click", clickButton() );
function clickButton ( pEvt:MouseEvent ):void
{
// display : broadcasted event
trace ( "broadcasted event" );
}

We listen to the click event on the button myButton and we change the clickButton function to be the listener. Once the user clicks on the button it broadcasts a click event which is listened to by the clickButton function.

Even if this syntax functions and doesn’t cause any problem for the moment, what happens if we specify an incorrect event name? Imagine in the following case that we make an error and listen to the event clicck:

myButton.addEventListener( "clicck", clicButton );

If you test the above code the clickButton function will never be triggered as the click event has an error and as it doesn’t exist it will never be broadcast. In order to avoid these problems, all event names are stored in classes linked to each event. When you need to listen to a specific event you should immediately think about the type of event that will be broadcast.

The classes reside in the flash.events package make up the ensemble of event classes in ActionScript 3. They can be divided into 2 categories.

  • Autonomous events

These are events broadcast by the objects without any user interaction, here are some classes linked to autonomous events: flash.events.Event: stores basic events flash.events.ProgressEvent: stores events linked to progressive loading flash.events.IOErrorEvent: stores events linked to loading errors

  • Interactive events

These are broadcasted events by the objects when a user interaction intervenes. flash.events.MouseEvent: stores mouse events flash.events.KeyboardEvent: stores keyboard events flash.events.TextEvent: stores textfield events

In our case we want to listen to an event that comes from a user’s mouse activity. We logically steer towards the MouseEvent class.

To get the event name we will target the static constant properties, the syntax relies on the following system:

ClasseEvent.MY_EVENT

To understand this concept, create a new Flash document and on an AS layer type the following line:

// display : click
trace ( MouseEvent.CLICK );

The MouseEvent class contains all the relative mouse elements, by targeting the static property CLICK we get the character string click that we change to the first parameter of the addEventListener method.

By targeting an event name by the intermediary of a static property we benefit from two advantages. If ever an information capture error occured in the verification of the code by the compiler, our code could not be compiled.

The following code would therefore fail:

myButton.addEventListener ( MouseEvent.CLICCK, clicButton );

… and displays the following error in the output message:

1119: Access to the CLICCK property can be undefined, via the reference of the Class static type.

In Flash CS3 and Flex Builder targeting an event class such as MouseEvent will display all of the events linked to this class. There will no longer be any reason to make a mistake in targeting your events.

In the long term, if the event name click changed or disappeared, in a future version of Flash player our old code pointing towards a constant would continue to function as its properties will be updated in future versions of Flash Player.

To listen to mouse clicks on our button we get the event name and we pass the method addEventListener:

myButton.addEventListener( MouseEvent.CLICK, clicButton );

This new way of storing event names brings a guarantee to the compilation but also sorts out any future compatibility worries. Let’s now see the different classes linked to existing events in ActionScript 3.

Event object

When an event is broadcast, an object is sent as a parameter to the listener function. This object is called event object.

It is for this reason that the listener function has to contain the signature of a broadcasted event type parameter. The type of event object corresponds to the type of class containing the event name. In our example it is the MouseEvent. The event object contains information linked to the event that is being broadcast. This information is available through the event object properties. We will now draw your attention to three of these properties, target, currentTarget and type.

  • The target property refers to the target object of the event. We can know from anywhere who is the source of the event propagation.
  • The currentTarget property refers to the broadcast object of the event. It is always the object that we call the addEventListener method.
  • The type property contains the name of the broadcasted event, in this case click

The following code gets a reference to the target object and the event name:

myButton.addEventListener ( MouseEvent.CLICK, clicButton );
function clicButton ( pEvt:MouseEvent ):void
{
// display : [object SimpleButton]
trace( pEvt.target );
// display : click
trace( pEvt.type );
}

We will come back to the differences between the target property and the currentTarget in the Event Propagation chapter.

The pEvt parameter defines a MouseEvent parameter type as the listened-to event is linked to a mouse event. The target property which is present in all broadcasted events allows a weak coupling between objects. When using the target property to target the broadcaster, we avoid having to reference the event object source directly by its name, which in case of modification, renders our code rigid and difficult to modify.

If the listener function doesn’t have a parameter in its signature which would accept the event object, an exception would be raised upon execution. The following code generates argument errors on execution:

myButton.addEventListener ( MouseEvent.CLICK, clicButton );
function clicButton ():void
{
}

Displayed in the output panel:

ArgumentError: Error #1063: No correspondence with the number of arguments on
Button_fla::MainTimeline/onMouseClick(). 0 warning(s), 1 error(s).

On execution, when the event is broadcast, no parameter accepts the event object, an exception is therefore raised. As you will remember, the new virtual machine (AVM2) conserves the execution types, if the type of event object in the signature of the listener function doesn’t correspond to the type of event object broadcast, the player will try to convert the event object. An error will be raised if the conversion is impossible.

Let’s look at this behavior by specifying a different type of event object in the listener function signature. We specify a flash.events.TextEvent parameter type in the listener function signature:

myButton.addEventListener ( MouseEvent.CLICK, clicButton );
function clicButton ( pEvt:TextEvent ):void
{
}

This code will display in the output panel:

TypeError: Error #1034: Failure of the type constraint: 
conversion of
flash.events::MouseEvent@2ee7601 in flash.events.TextEvent is impossible.

On the other hand, we can use the common flash.events.Event type which is compatible with all event classes:

myButton.addEventListener ( MouseEvent.CLICK, clicButton );
function clicButton ( pEvt:Event ):void
{
}

Let’s look at the Event class in more detail:

The event class

As we previously saw, there are a group of classes in the flash.events package which contain all the event type objects that can be broadcast. The parent class is the Event class to all the event objects.

This class defines the majority of broadcasted events in ActionScript 3, the traditional Event.ENTER_FRAME event is contained in the Event class, like the Event.COMPLETE event unique to any loading object an external element in the Flash player.

In a new Flash document, create a MovieClip symbol and put an occurrence of this clip called myClip on the stage.

The following code allows you to listen to the event Event.ENTER_FRAME alongside a MovieClip:

monClip.addEventListener ( Event.ENTER_FRAME, execute );
function execute ( pEvt:Event ):void
{
// display : [object MovieClip] : enterFrame
trace( pEvt.target + " : " + pEvt.type );
}

The Event.ENTER_FRAME event has the characteristic that it is automatically broadcast when a listener is subscribed to. As we have previously seen, certain events broadcast on the other hand event objects of the extended type of Event class. This is the case of events stemming from the mouse or the keyboard.

When an event caused by the mouse is broadcast, it is not an event object of the Event type that we will receive in our listener function, but is a flash.events.MouseEvent type.

Why do we get an event object of a different type for a mouse event?

This is what we will discover together in the part called Event sub-classes.








Adobe Training center


Mediabox Training Centre © 2000 - 2008 All rights reserved.
Adobe Authorized Training Centre. State convention under number 25 14 02167 14.
Mediabox : SARL au capital de 62.000€ - Activity number: 25 14 02167 14 - SIRET : 493 716 468 00027
MEDIABOX, 102 Avenue des Champs Elysées, 75008 PARIS - Tel. +33(0)2.31.91.96.89 - Fax. +33(0)2.72.68.56.42