One By One Design

Passing Arguments to Event Listening Methods

I’ve seen this question asked in several forums. Enough, anyway, that I would remark on it. The question takes many a form, but it boils down to this: How does one pass arguments to a method acting as an event listener in Actionscript 3?

In general there are three broad routes to take:

  • Using a custom object and accessing its properties with the currentTarget property of whatever Event the method is listening for.
  • Dispatching a custom event which can contain its own properties.
  • Using a Dictionary object instance to hold references associated with event dispatching objects.

 Let’s take a little look at each of these.

With the custom object approach, arguments you wish to access in an event listener are added to the event dispatching object as properties. This is most useful when you want the event handling to be performed in a class which contains the dispatching object.

A quick example:

The custom object:

package { 

	import flash.display.Sprite; 

	public class  CustomObject extends Sprite { 

		private var _foo:Boolean; 
		private var _bar:int; 

		public function CustomObject(foo:Boolean, bar:int):void { 
			_foo = foo; 
			_bar = bar; 

			graphics.beginFill(0x000077); 
			graphics.drawRect(0, 0, 100, 50); 
			graphics.endFill(); 
		} 

		public function get bar():int { return _bar; } 

		public function set bar(value:int):void { 
			_bar = value; 
		} 

		public function get foo():Boolean { return _foo; } 

		public function set foo(value:Boolean):void { 
			_foo = value; 
		} 
	} 
}

And document class:

package { 

	import flash.display.Sprite; 
	import flash.events.MouseEvent; 

	public class CustomObjectTest extends Sprite { 

		public function CustomObjectTest():void { 
			var co:CustomObject = new CustomObject(true, 23); 
			co.addEventListener(MouseEvent.CLICK, onClick); 
			addChild(co); 
		} 

		private function onClick(me:MouseEvent):void { 
			trace (me.currentTarget.foo, me.currentTarget.bar); 
		} 
	} 
}

As you can see, the foo and bar properties are “passed” to the event listening method as actual properties of the object clicked.

The custom event approach is most useful when you wish event handling to be done within the dispatching object. Here the “passed” arguments are contained inside properties of the dispatched event.

Example:

Custom event class:

package { 

	import flash.events.Event; 

	public class CustomEvent extends Event { 

		public static const CUSTOM:String = "customEvent"; 

		private var _foo:Boolean; 
		private var _bar:int; 

		public function CustomEvent(type:String, foo:Boolean, bar:int):void { 
			super(type); 

			_foo = foo; 
			_bar = bar; 
		} 

		public function get foo():Boolean { return _foo; } 

		public function get bar():int { return _bar; } 
	} 
}

A custom object which dispatches the event:

package { 

	import flash.display.Sprite; 
	import flash.events.MouseEvent; 

	public class CustomEventObject extends Sprite { 

		public function CustomEventObject():void { 
			graphics.beginFill(0x000077); 
			graphics.drawRect(0, 0, 100, 50); 
			graphics.endFill(); 

			addEventListener(MouseEvent.CLICK, sendCustomEvent); 
		} 

		private function sendCustomEvent(me:MouseEvent):void { 
			dispatchEvent(new CustomEvent(CustomEvent.CUSTOM, true, 23)); 
		} 
	} 
}

And finally a document class which ties it all together:

package { 

	import flash.display.Sprite; 

	public class CustomEventTest extends Sprite { 

		public function CustomEventTest():void { 
			var ceo:CustomEventObject = new CustomEventObject(); 
			ceo.addEventListener(CustomEvent.CUSTOM, onCustomEvent); 
			addChild(ceo); 
		} 

		private function onCustomEvent(ce:CustomEvent):void { 
			trace(ce.foo, ce.bar); 
		} 
	} 
}

Here you can see the “arguments” are accessed in the event listener as properties of the dispatched event.

Finally, the Dictionary approach is probably the least object oriented of the bunch but sometimes it’s just what the doctor ordered. Here the arguments we wish to pass to the event listener are stored in a dictionary and associated with the event dispatching object. Using this approach it’s easy to maintain everything in a single class such as this:

package { 

	import flash.display.Sprite; 
	import flash.events.MouseEvent; 
	import flash.utils.Dictionary; 

	public class DictionaryTest extends Sprite { 

		private var _dict:Dictionary 

		public function DictionaryTest():void { 
			_dict = new Dictionary(); 

			var clickableSprite:Sprite = new Sprite(); 
			clickableSprite.graphics.beginFill(0x000077); 
			clickableSprite.graphics.drawRect(0, 0, 100, 50); 
			clickableSprite.graphics.endFill(); 
			clickableSprite.addEventListener(MouseEvent.CLICK, onClick); 

			_dict[clickableSprite] = [true, 23]; 

			addChild(clickableSprite); 
		} 

		private function onClick(me:MouseEvent):void { 
			trace (_dict[me.currentTarget][0], _dict[me.currentTarget][1]); 
		} 
	} 
}

Of course there are other more or less complicated methods of getting the job done, but they follow the same general guidelines (such as adding properties willy nilly to dynamic classes like MovieClips, which is basically the same as using a custom object but not generally recommended, or using objects as associative arrays rather than a Dictionary instance).

Posted by