In ActionScript 3.0, can you use addEventListener for one class to react to the function call of another class? - actionscript-3

I know how to use addEventListener for one class to react to another class's button being clicked on. What if you want to use it for a more general purpose than that? What if you want to use it to react to one of the member functions of the other class being called? Is there a syntax for that? Thanks!
Edit: Please note that I have already Googled for the answer.

If you want to listen for another class' member function call, you need that function call to dispatch an Event. This is as simple as...
Listener Class
addEventListener("customEvent", listenerFunc);
Dispatcher Class (extends EventDispatcher / implements IEventDispatcher)
dispatchEvent(new Event("customEvent"));
As long as the listener class is above the dispatcher class in the object hierarchy, this will work perfectly. If not, you may want to use some sort of Global EventDispatcher class and register all listeners on that.

You can create your own events and dispatch them from the other class and listen to them in your listening class. Here is some code
In class A (assuming it inherits EventDispatcher)
public function classAMethod():void
{
dispatchEvent(new Event("someCustomTypeForEvent"));
}
In class B (assuming it has a reference to Class A)
public function classBMethod():void
{
classA.addEventListener("someCustomTypeForEvent",customHandler);
}
public function customHandler(e:Event):void
{
trace("handle event");
}

It's like in JAVA for java.awt.Component instances and all Objects that extends java.awt.Component; in AS3 you may add Listeners to all Objects that extends flash.display.Sprite instances which implements methods of IEventDispatcher for you...
So, If you have a class which do not extends flash.display.Sprite, you'll have to extend EventDispatcher in order to add Listeners to your instances and handle Events...
If the class may not extend EventDispatcher, you'll have to implement the IEventDispatcher.
Here is a [class MainClass] that extends [class MovieClip]
This MainClass instance, creates :
An instance of [class ObjectA] which extends [class Object] and implements IEventDispatcher,
An instance of [class ObjectB] which extends [class EventDispatcher]
Here is the code that use the extension method and the implementation method :
I hope this quick done example will help you...
(And sorry for my English, this is not my native language.)
in MainClass.as :
package com
{
import flash.utils.getDefinitionByName;
import flash.display.MovieClip;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import flash.utils.getQualifiedSuperclassName;
import com.classes.ObjectA;
import com.classes.ObjectB;
import flash.events.Event;
public class MainClass extends flash.display.MovieClip
{
private static const DEBUG:Boolean = true;
private static var instance:MainClass;
private static var instanceOfA:ObjectA;
private static var instanceOfB:ObjectB;
public function MainClass()
{
MainClass.debug("MainClass constructor called");
MainClass.debug(getClassInformations(MainClass));
MainClass.debug(getClassInformations(ObjectA));
MainClass.debug(getClassInformations(ObjectB));
instanceOfA = new ObjectA();
instanceOfB = new ObjectB();
instanceOfA.addEventListener(ObjectA.DO_SOMETHING_EVENT,onInstanceOfA_doSomething,false,0,false);
instanceOfB.addEventListener(ObjectB.DO_SOMETHING_EVENT,onInstanceOfB_doSomething,false,0,false);
instanceOfA.doSomething();
instanceOfB.doSomething();
}
public static function onInstanceOfA_doSomething(e:Event):void
{
trace("An ObjectA has Dispatched An Event of type \"" + e.type + "\"" + " on " + e.target);
}
public static function onInstanceOfB_doSomething(e:Event):void
{
trace("An ObjectB has Dispatched An Event of type \"" + e.type + "\"" + " on " + e.target);
}
public static function getDebugMode():Boolean
{
return DEBUG;
}
public static function debug(string:String)
{
if (getDebugMode())
{
trace(string);
}
}
public static function getClassInformations(someClass:Class):String
{
var clss:Object = null;
var supClss:Object = null;
clss = getDefinitionByName(getQualifiedClassName(someClass));
try
{
supClss = getDefinitionByName(getQualifiedSuperclassName(someClass));
}
catch (e:ArgumentError)
{
// Has no superClass (ex:Object)
}
if (supClss != null)
{
return ("class " + clss + " extends " + supClss);
}
else
{
return ("class " + clss);
}
}
}
}
in ObjectB.as (simplest way):
package com.classes{
import com.MainClass;
import flash.events.EventDispatcher;
import flash.events.Event;
public class ObjectB extends EventDispatcher {
public static var DO_SOMETHING_EVENT:String = "do_something_event";
private var onDoSomethingEvent:Event = new Event(DO_SOMETHING_EVENT,false,false);
public function ObjectB() {
MainClass.debug("constructor ObjectB called");
}
public function doSomething():void{
this.dispatchEvent(onDoSomethingEvent);
}
}
}
in ObjectA.as (there you must implement all the methods of the interface IEventDispatcher):
package com.classes
{
import com.MainClass;
import flash.events.IEventDispatcher;
import flash.events.EventDispatcher;
import flash.events.Event;
public class ObjectA implements IEventDispatcher
{
public static var DO_SOMETHING_EVENT:String = "do_something_event";
private var onDoSomethingEvent:Event = new Event(DO_SOMETHING_EVENT,false,false);
private var dispatcher:EventDispatcher;
public function ObjectA()
{
dispatcher = new EventDispatcher(this);
MainClass.debug("constructor ObjectA called");
}
public function doSomething():void
{
this.dispatchEvent(onDoSomethingEvent);
}
public function addEventListener(
event_type:String,
event_listener:Function,
use_capture:Boolean = false,
priority:int = 0,
weakRef:Boolean = false
):void
{
// implements addEventListener here
dispatcher.addEventListener(event_type, event_listener, use_capture, priority, weakRef);
}
public function dispatchEvent(e:Event):Boolean
{
// implements dispatchEvent here
return dispatcher.dispatchEvent(e);
}
public function removeEventListener(
event_type:String,
event_listener:Function,
use_capture:Boolean = false
):void
{
// implements removeEventListener here
dispatcher.removeEventListener(event_type, event_listener, use_capture);
}
public function hasEventListener(type:String):Boolean
{
// implements hasEventListener here
return dispatcher.hasEventListener(type);
}
public function willTrigger(type:String):Boolean
{
// implements willTrigger here
return dispatcher.willTrigger(type);
}
}
}
Note that if you extend an EventDispatcher, you may also want to override some methods.
In this case, you must use the "override keyword as :
public override function dispatchEvent (e:Event):Boolean {
// a method of EventDispatcher may be overridden if needed !
// do what you need HERE...
return dispatchEvent(e);
}
In AS3 you must specify the override keyword or you'll get an Error 1024:
"Overriding a function that is not marked for override."
When you create a new EventDispatcher through implement or extend, you may also specify additional arguments and methods to this object as:
public function ListenerObject (v:View,m:Main) {
dispatcher = new EventDispatcher(this);
view = v;
master = m;
}
public function getView ():View {
return view;
}
public function getMain ():Main {
return master;
}
then use those methods in the callback method as :
public function callback(e:Event):void{
e.target.getView ();
//...
}

Related

AS3 dispatchEvent not working on class

i created this event class:
package com.site {
import flash.events.Event;
public class clientEvent extends Event {
public static const connectionSucceeded: String = "connectionSucceeded";
public var prams: Object;
public function clientEvent(type: String, prams: Object) {
super(type);
this.prams = prams;
}
override public function clone(): Event {
return new clientEvent(type, prams);
}
}
}
and on other class (Not main) im writed:
dispatchEvent(new clientEvent(clientEvent.connectionSucceeded, new Object()));
Im import the class and its return this error:
1180: Call to a possibly undefined method dispatchEvent.
The other class should extend EventDispatcher class.
See: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/EventDispatcher.html

as3 initialize class constructor from another class

I am very FRESHLY new to packages so forgive my simple question. How do I initialize the docTwo class and constructor function? I figured out how to call a static function from the main class but not to init another class. Thanks
myDocClass.as
package {
import flash.display.MovieClip;
import docTwo;
public class myDocClass extends MovieClip
{
var Hello:String = "Hi there";
public function myDocClass ()
{
trace("And all the people said... " + Hello);
docTwo.docTwo(); /// Does NOT WORK. How do I call this or init class?
thisWorks();
// Below call Works
docTwo.docTwoFunction();
}
public function thisWorks()
{
trace("Cool Beans! This one worked");
}
}/// end of Class
}
docTwo.as
package {
import flash.display.MovieClip;
public class docTwo{
public function docTwo()
{
trace("Trying to get this to work!");
docTwoFunction(); // How do I call this from here?
}
static public function docTwoFunction()
{
trace("I am inside docTwo. Woo hoo!");
}
}
}
Try to change your myDocClass like this:
public class myDocClass extends MovieClip
{
var Hello:String = "Hi there";
var myDocTwo:docTwo ;
public function myDocClass ()
{
trace("And all the people said... " + Hello);
myDocTwo = new docTwo();
...
...
Note , they're both placed in the same package.

Is it possible to listen the event triggered by another class?

I've got 3 classes:
The class that recognizes the change in URL (using SWFAddress by Asual):
package swfaddress {
import flash.display.MovieClip;
import com.asual.swfaddress.*;
public class SwfAddress extends MovieClip {
private var dispatcher:Dispatch = new Dispatch;
public function SwfAddress():void {
SWFAddress.addEventListener(SWFAddressEvent.CHANGE, onChange);
}
private function onChange(e:SWFAddressEvent):void {
dispatcher.changed();
}
}
}
The class "Dispatch" that validates the URL and dispatching Event when finished
package swfaddress {
import flash.events.Event;
import flash.events.EventDispatcher;
public class Dispatch extends EventDispatcher {
public static const CHANGED:String = "changed";
public function changed ():void {
// some operations validating the URL
dispatchEvent(new Event(Dispatch.CHANGED));
}
}
}
Other class in other package that should receive info when the validation process has finished.
package menu {
import swfaddress.*
public class MenuPanel extends MovieClip {
var swfRead:Dispatch = new Dispatch;
public function MenuPanel():void {
swfRead.addEventListener(Dispatch.CHANGED, onChange);
}
private function onChange(e:Event):void {
trace("Hello World");
}
}
And the "Hello World" never appeared in the output window - so I'm not sure if it's possible that my MenuPanel has a chance to receive an info about completing the validation triggered by some other class?
You are creating two different instances of the dispatcher, and so the instance that is being called to validate your URL is not the same instance that you are listening to in the MenuPanel class.
A simple way around this would be to make the Dispatch class a singleton, so that only one instance of it exists and you can reference it from different points in your application. This works by giving the Dispatch class a static method that returns a self-contained instance of itself. You then call Dispatch.getInstance() whenever you want a reference to the class instead of using the new keyword.
Dispatch:
package swfaddress
{
import flash.events.Event;
import flash.events.EventDispatcher;
public class Dispatch extends EventDispatcher
{
// singleton instance
private static var _instance:Dispatch;
private static var _allowInstance:Boolean;
public static const CHANGED:String = "changed";
// get singleton instance of Dispatch
public static function getInstance():Dispatch
{
if (Dispatch._instance == null) {
Dispatch._allowInstance = true;
Dispatch._instance = new Dispatch();
Dispatch._allowInstance = false;
}
return Dispatch._instance;
}
public function Dispatch()
{
if (!Dispatch._allowInstance)
{
throw new Error("Error: Use Dispatch.getInstance() instead of the new keyword.");
}
}
public function changed():void {
//some operations validating the URL
dispatchEvent(new Event(Dispatch.CHANGED));
}
}
}
Getting a reference:
private var dispatcher:Dispatch = Dispatch.getInstance();

Custom Events with Singleton EventDispatcher, using getDefinition from child

EDIT: For whatever reason, it works in the browser but not when compiled/debugged within the IDE.
I can't get my external SWFs to pick up on dispatches from my singleton event manager (EventDispatcher). Here are the particulars:
I add children from an external SWF using the getDefinition method to my main SWF.
I'm using a singleton EventDispatcher that is in charge of listeners and dispatching.
Using a custom event class.
In this code, I am trying to get a mute button to tell the main SWF that the mute icon has been clicked (SoundClipEvent.MUTE_CLICK). After the sound has been muted, it should dispatch the event (SoundClipEvent.STATE) and confirm to the muteIcon the state. Currently, the mute icon successfully dispatches the MUTE_CLICK event and the main SWF document class is able to pick it up. MuteIcon (child SWF MC) hears nothing from the singleton.
Your help in this problem is greatly appreciated!
SoundClipManager.as:
import flash.events.Event;
import flash.events.EventDispatcher;
public dynamic class SoundClipManager extends EventDispatcher {
private static var isMuted:Boolean;
public function SoundClipManager(blocker:SingletonBlocker):void {
super();
//
if (blocker == null) {
throw new Error("Error: Instantiation failed; Use SoundClipManager.getInstance()");
}
}
public static function get muted():Boolean {
return SoundClipManager.isMuted;
}
public static function set muted(value:Boolean) {
SoundClipManager.isMuted = value;
//
SoundClipManager.getInstance().dispatchEvent(new SoundClipEvent(SoundClipEvent.STATE,SoundClipManager.muted));
}
public static function getInstance():SoundClipManager {
if (instance == null) {
instance = new SoundClipManager(new SingletonBlocker());
}
return instance;
}
public override function dispatchEvent(evt:Event):Boolean {
return super.dispatchEvent(evt);
}
private static function stateChanged(evt:*) {
trace('state changed!');
}
}
internal class SingletonBlocker {}
MuteIcon.as
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
//
public dynamic class IconMute extends MovieClip {
public function IconMute() {
this.addEventListener(Event.ADDED_TO_STAGE,this.addedToStage);
//
SoundClipManager.getInstance().addEventListener(SoundClipEvent.STATE,this.soundClipManagerStateChanged);
}
//
// Methods, Private
//
//
// Events
//
private function muteClick(evt:MouseEvent) {
SoundClipManager.getInstance().dispatchEvent(new SoundClipEvent(SoundClipEvent.MUTE_CLICK));
}
//
private function addedToStage(evt:Event) {
this.addEventListener(MouseEvent.CLICK,this.muteClick);
}
//
private function soundClipManagerStateChanged(evt:*) {
trace("state changed!");
}
}
SoundClipEvent.as
package {
//
import flash.events.Event;
//
public class SoundClipEvent extends Event {
public static const MUTE_CLICK:String = "muteClick";
public static const STATE:String = "state";
//
public var muted:Boolean;
public function SoundClipEvent(type:String,muted:Boolean = false) {
if(muted) this.muted = muted;
//
super(type,true,false);
}
}
}
getDefinitionByName(className) method will work only if className was mensioned somewhere in your code. You may just import className class in a file where you're going to call getDefinitionByName(className). That should help!

Override Clone() in custom event for AS3... need help

I have created a custom even class which is pretty basic. But when calling an event and then relaying that event to another class I have encountered the "cannot transform thisEvent into thisOtherEvent" error.
I realize this is because I needed to override the Clone function in my custom event like so:
package com
{
import flash.disply.*;
import flash.events.Event;
public class MyCustomEvents extends Event
{
public static const SOME_EVENT:String = "some_event";
public var info:Object;
public function MyCustomEvents($type:String, $info:Object,$bubbles:Boolean = false, $cancelable:Boolean = false)
{
super($type, $bubbles, $cancelable);
this.info = $info;
}
public override function clone():Event {
return new MyCustomEvents($type, $bubbles, $cancelable);
}
}
}
However I am still getting this error when I dispatch the event. Anything else I might be missing?
here is the error:
TypeError: Error #1034: Type Coercion failed: cannot convert com.greensock.events::TransformEvent#d8df709 to com.customEvents.MyCustomEvents.
I tried casting the event in the code like so:
var deleteImgEvent:MyCustomEvent = new MyCustomEvent(MyCustomEvents.IMAGE_DELETE, {imgData: getImg}, true, false); this.dispatchEvent(deleteImgEvent as MyCustomEvents);
Still no luck.
UPDATE:
Ok, seems like the problem is in the greensock Transform library. When the event handler for my custom event is called, I run a function of the TransformManager class.
_manager.deleteSelection();
Inside that class it dispatched a TransformEvent. Not sure why, but it is reading that delete event as a MyCustomEvent.
/**
* #usage
* var myEvent:CustomEvent = new CustomEvent(CustomEvent.EVENT_TYPE_A, { integerRelatedToEvent: 5, stringRelatedToEvent: 'easy' });
* addEventListener(CustomEvent.EVENT_TYPE_A, traceCustomEvent);
* dispatch(myEvent);
* function traceCustomEvent ($e:CustomEvent):void {
* trace($e.type);
* }
*/
package {
import flash.events.Event;
public class CustomEvent extends Event {
// Types:
public static const EVENT_TYPE_A:String = 'CustomEvent.EVENT_TYPE_A';
public static const EVENT_TYPE_B:String = 'CustomEvent.EVENT_TYPE_B';
// Components:
private var _customDatum:Object;
public function get customDatum ():Object { return _customDatum; }
public function CustomEvent ($type:String, $customDatum:Object) {
super($type);
_customDatum = $customDatum;
}
public override function clone ():Event {
return new CustomEvent(type, _customDatum);
}
}
}
"When creating your own custom Event
class, you must override the inherited
Event.clone() method in order for it
to duplicate the properties of your
custom class. If you do not set all
the properties that you add in your
event subclass, those properties will
not have the correct values when
listeners handle the redispatched
event."
package com.events;
{
import flash.events.Event;
public class XMLLoaderEvent extends Event
{
public static const XML_LOADED:String = "XML_Loaded";
public var data:*;
public var properties:Object;
public function XMLLoaderEvent( type:String,_data:*,bubbles:Boolean = false,cancelable:Boolean = false):void
{
super( type, bubbles, cancelable );
data = _data;
}
// Override clone
override public function clone():Event
{
return new XMLLoaderEvent( type, data, bubbles, cancelable);
}
}
}
Don't know if that's it but you have an extra parameter $info:Object into your custom event, but you don't pass it in your clone contructor.
return new MyCustomEvents(type, info, bubbles, cancelable);
I think you need the clone function to return a MyCustomEvents type. Not an Event type. And you need to add the info parameter as stated by the previous poster.
package com {
import flash.display.*;
import flash.events.Event;
public class MyCustomEvents extends Event {
public static const SOME_EVENT:String = "some_event";
public var info:Object;
public function MyCustomEvents($type:String, $info:Object,$bubbles:Boolean = false, $cancelable:Boolean = false) {
super($type, $bubbles, $cancelable);
this.info = $info;
}
public override function clone():MyCustomEvents {
return new MyCustomEvents(this.type, this.info, this.bubbles, this.cancelable);
}
}
}