Monday, April 21, 2008
AS3 dispatching events with arguments...
Monday, April 21, 2008
(There are two (2) updates to this post):
What I have is a custom Event class for dispatching events, and its imported and used from within another class. A third document class listens to the class for events. I'd like to get properties of the returned event like we could in AS2 hackery, but right now I only seem to be able to pass arguments, and then you'd have to know which argument is what to make them useful (bad).
The custom event class:
package
{
import flash.events.Event;
public class EventType extends Event
{
public var arg:*;
public var properties:Object;
public function EventType( type:String,
bubbles:Boolean = false,
cancelable:Boolean = false,
... a:* ):void
{
super( type, bubbles, cancelable );
arg = a;
}
// Override clone
override public function clone():Event
{
return new EventType( type, bubbles, cancelable, arg );
};
}
}
From within the class dispatching the event ("10" is just a test):
...
public static const UPDATED:String = "updated";
...
dispatchEvent( new EventType( ClassName.UPDATED, false, false, "10" ) );
And from the document class:
...
classInstance.addEventListener( PartitionGauge.UPDATED, updateListener );
...
private function updateListener( e:EventType ):void
{
trace( e.type );
trace( e.arg.length );
trace( e.arg[0] ); // wtf is this really supposed to be?
}
So you can see that this approach does work, but you'd have to have special knowledge to get the .arg from the returned event, and you'd also need to know what each index of the returned arguments actually map to. It would be cool to be able to pass back a property on the event itself, like:
trace( e.value );
and thing like that. I haven't figured that part out quite yet, and I've spent time googling and haven't found a whole lot just yet. But there must be a pretty easy to use solution for this kind of thing. I'd hope.
Update:
Well, I've come across a different approach, and it's similar to the one above, but instead of arguments it uses properties on a returned object. At least that is more approachable, although you need an intermediary object to inspect through.
Here is the class:
package
{
import flash.events.Event;
public class CustomEvent extends Event
{
public static const DEFAULT_NAME:String = "CustomEvent";
public static const ON_UPDATE:String = "onUpdate";
public var params:Object;
public function CustomEvent( $type:String,
$params:Object,
$bubbles:Boolean = false,
$cancelable:Boolean = false )
{
super( $type, $bubbles, $cancelable );
this.params = $params;
}
public override function clone():Event
{
return new CustomEvent( type, this.params,
bubbles, cancelable );
}
public override function toString():String
{
return formatToString( "CustomEvent",
"params", "type",
"bubbles", "cancelable" );
}
}
}
And within my class that dispatches the event (test properties here):
...
import CustomEvent;
...
this.dispatchEvent( new CustomEvent( CustomEvent.ON_UPDATE,
{value:"10", foo:"hello" } ) );
And now in the document class
...
classInstance.addEventListener( CustomEvent.ON_UPDATE, updateListener );
...
private function updateListener( e:CustomEvent ):void
{
trace( e.type );//onUpdate
trace( e.params.value );//10
trace( e.params.foo );//hello
}
So, that's a little better. You still have to access through the params object instead of simply on the returned event object itself, but it's better, don't you think?
You don't have to parse through arcane argument indexes wondering what they are. At least with properties you can use the name of the property outright. And that makes the whole thing more approachable.
Update 2 (yes, another one):
Well, here is something that is more approachable still.
package
{
import flash.events.Event;
public class CustomChangeEvent extends Event
{
public static const CHANGE:String = "EVENT_CUST_CHANGE";
public var who:*;
public var value:Number;
public function CustomChangeEvent( type:String, who:*,
value:Number )
{
super( type );
this.who = who;
this.value = value;
}
public override function clone():Event
{
return new CustomChangeEvent( type,
this.who,
this.value );
}
}
}
You will get code completion in FlashDevelop, you can access the properties of the return event object, you get strong typing for some of it (I left who as a wildcard right now since it's not settled what it will be yet, probably a Sprite though). When I make that change, the class will have strong typing through it, and everything will be nice and neat.
I think this approach will truly work well in any circumstance.
Comments:
There are currently 5 Comments:
-
“I've used this method to pass parameters before (it involves calling a custom function which simply returns the Event function).
In this example, I want to change a button's alpha value based on predetermined amounts (and want to simply pass that value, instead of having a "switch" or "if" statement in the called function):
-----------------------
myButton1.addEventListener(MouseEvent.CLICK,customAlphaChange(.5));
myButton2.addEventListener(MouseEvent.CLICK,customAlphaChange(.8));
function customAlphaChange(theValue:Number):Function {
return function(e:MouseEvent) {
e.target.alpha=theValue;
}
}”