Custom Event not working - actionscript-3

I have created a Custom Event, that is fired from a custom component. It should be catched in the main application to change the selectedindex of the viewstack.
But this doesn't work, and I can't figure out why.
This is my Custom Event:
package events
{
import flash.events.Event;
public class ChangeSelectedIndex extends Event
{
public static var index_passed:String = "Index passed";
private var index:int;
public function ChangeSelectedIndex(i:int, type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type,bubbles, cancelable);
index = i;
}
public function get getIndex():int
{
return index;
}
}
}
This is how I fire the event:
protected function checkUsernameExistsDbSucces(event:ResultEvent):void
{
dispatchEvent( new ChangeSelectedIndex(1,ChangeSelectedIndex.index_passed,false,false));
}
And this is my function to catch the event:
private function changeSelectedIndexHandler(event:ChangeSelectedIndex):void
{
mainViewStack.selectedIndex = event.getIndex;
}

In order for your handler to be called when the event is dispatched, you need to add an event listener to your custom component.
myCustomComponent.addEventListener ( ChangeSelectedIndex.index_passed, changeSelectedIndexHandler);
Make sure this line is within the same scope as both your handler function and myCustomComponent, otherwise there will be an error.

Related

Action script 3 Event And Event dispacher

what's diffrance between Event and EventDispacher
when I create Custom Event class how I create it and extend it to Event or eventDispacher ?
package
{
import flash.events.Event;
that's how you can extend a event :
public class CustomEvent extends Event
{
public static const CUSTOM_EVENT:String = "customEvent";
public var param:Object;
public function BannerEvent( type:String, param:Object = null, bubbles:Boolean = false, cancelable:Boolean = false )
{
super( type, bubbles, cancelable );
this.param = param?param: { };
}
}
}
EventDispatcher will, as it says in the name dispatch an event.
For example if your custom component implements IEventDispatcher, it will be able to dispatch events.
In Flash, all DisplayObjects can dispatch events by default.
In Flex, all UIComponents can dispatch events by default.
To create a custom event, you can do the following:
package{
import flash.events.Event;
public class MyCustomEvent extends Event
{
private var _test:String;
public function MyCustomEvent(test:String)
{
super("MyCustomEvent", false, false);
this.test = test;
}
public function set test(value:String):void{
_test = value;
}
public function get test():String{
return test;
}
}}
Then to dispatch it, you either dispatch an event from a Display Object or you create a custom component that implements IEventDispatcher
and do this:
dispatchEvent(new MyCustomEvent("This is a test event"));
Cheers

Custom event dispatchment location

I've been looking into custom event (listeners) for quite some time, but never succeeded in making one. There are so many different methods, extending the Event class, but also Extending the EventDispatcher class, very confusing!
I want to settle with this once and for all and learn the appropriate technique.
package{
import flash.events.Event;
public class CustomEvent extends Event{
public static const TEST:String = 'test'; //what exac is the purpose of the value in the string?
public var data:Object;
public function CustomEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false, data:Object = null):void
{
this.data = data;
super();
}
}
}
As far as I know a custom class where you set the requirements for the event to be dispatched has to be made:
package
{
import flash.display.MovieClip;
public class TestClass extends MovieClip
{
public function TestClass():void {
if (ConditionForHoldToComplete == true) {
dispatchEvent(new Event(CustomEvent.TEST));
}
}
}
}
I'm not sure if this is correct, but it should be something along the lines of this.
Now What I want is something like a mouseevent, which can be applied to a target and does not require a specific class.
It would have to work something like this:
package com.op_pad._events{
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.EventDispatcher;
import flash.events.Event;
public class HoldEvent extends Event
{
public static const HOLD_COMPLETE:String = "hold completed";
var timer:Timer;
public function SpriteEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super( type, bubbles, cancelable );
timer = new Timer(1000, 1);
//somehow find the target where is event is placed upon -> target.addEventlistener
target.addEventListener(MouseEvent.MOUSE_DOWN, startTimer);
target.addEventListener(MouseEvent.MOUSE_UP, stopTimer);
}
public override function clone():Event
{
return new SpriteEvent(type, bubbles, cancelable);
}
public override function toString():String
{
return formatToString("MovieEvent", "type", "bubbles", "cancelable", "eventPhase");
}
//////////////////////////////////
///// c o n d i t i o n s /////
//////////////////////////////////
private function startTimer(e:MouseEvent):void
{
timer.start();
timer.addEventListener(TimerEvent.TIMER_COMPLETE, complete);
}
private function stopTimer(e:MouseEvent):void
{
timer.stop()
}
public function complete(e:TimerEvent):void {
dispatchEvent(new HoldEvent(HoldEvent.HOLD_COMPLETE));
}
}
}
This obviously won't work, but should give you an idea of what I want to achieve. This should be possible because mouseevent can be applied to about everything.The main problem is that I don't know where I should set the requirements for the event to be executed to be able to apply it to movieclips and sprites.
You are almost there actually, just for the last part, wouldn't this be more of an OOP related issue than stricly a confusion about the way of using custom events ?
Usually, Events in AS3 are value objects whose sole responsibility is to transport information from the event dispatcher to the listener(s). The dispatcher dispatches the event each time a defined momentum is reached, and the listener(s) may or may not react when this happens.
In the example above, I guess it is up to the listener to start a timer and so on when a mouse-down has been detected. In a more sophisticated context the Event could independently trigger more than one listeners actioning separate tasks which neither the Dispatcher nor the Event itself should have to bother about, that is probably why it's worth avoiding amending the dispatcher or the event itself with any soever logic.
For your very example, you could maybe create a handler checking if the mouse has been held down?
The following is just pseudocode, and there are obviously tons of other ways to get to the same result:
public class MouseDownHandler
{
// ...
public function( target:Sprite ) {
this.target = target;
start();
}
public function start():void{
// Listen for the target's mouseUp event
}
public function dispose():void{
// Stop listeners and eventually the timer
}
private function onMouseDown(e:MouseEvent):void{
// Start timer + listening for the stage's mouse up event (target.stage)
}
private function onMouseUp(e:Event):void{
// Cancel timer
}
private function onTimerComplete(e:TimerEvent):void {
dispatchEvent(new HoldEvent(HoldEvent.HOLD_COMPLETE));
}
}
Which could be reused for example this way:
var mc:MovieClip = new MovieClip(); ...
var mouseHandler:MouseDownHandler = new MouseDownHandler(mc);
mouseHandler.addEventListener(HoldEvent.HOLD_COMPLETE, onMcHoldComplete);
... or this way :
public class TestMovieClip extends MovieClip
{
private var mouseHandler:MouseDownHandler;
public function TestMovieClip() {
mouseHandler = new MouseDownHandler(this);
mouseHandler.addEventListener(HoldEvent.HOLD_COMPLETE, onMouseHoldComplete);
}
private function onMouseHoldComplete(e:HoldEvent):void {
// Do something
}
}
I just use robber penners signals. Very easy to use.
http://github.com/robertpenner/as3-signals

How do I handle a custom event in ActionScript 3?

I've created an Event Handler/Listener like so:
import flash.events.Event;
public class DanielEvent extends Event {
public var data:*;
public static const APP_STARTED:String = "APP_STARTED";
public function DanielEvent(n:String, data:*){
this.data = data;
super(n)
}
}
Listening to an event using:
addEventListener(DanielEvent.APP_STARTED, appStarted);
Dispatching an event by:
dispatchEvent(new DanielEvent("APP_STARTED", "test"))
And receiving the data by:
private function appStarted(e:Event){
trace(e.data)
}
But I get the error:
Access of possibly undefined property
data through a reference with static
type flash.events:Event.
You have to use your custom event type in the event handler, if you want to access the data property:
private function appStarted(e:DanielEvent): void {
trace(e.data);
}
your event handler is passed a DanielEvent, not an Event:
private function appStarted(e:DanielEvent):void
{
trace(e.data);
}
also. you should also use your constant for your dispatch instead of passing a string, like you've done for your listener:
dispatchEvent(new DanielEvent(DanielEvent.APP_STARTED, "test"));
and don't forget to override clone() if you are planning on dispatching that event more than once.
public override function clone():Event
{
return new DanielEvent(n, data);
}

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);
}
}
}

How do I modify existing AS3 events so that I can pass data?

So I want a way to set up events so that I can pass data without creating closures \ memory leaks. This is as far as I have got:
package com.events {
import flash.events.Event;
public class CustomEvent extends Event {
public static const REMOVED_FROM_STAGE:String = "removedFromStage";
public var data:*;
public function CustomEvent(type:String, customData:*=null, bubbles:Boolean=false, cancelable:Boolean=false) {
super(type, bubbles, cancelable);
this.data = customData;
}
public override function clone():Event {
return new CustomEvent(type, data, bubbles, cancelable);
}
public override function toString():String {
return formatToString("CustomEvent", "type", "data", "bubbles", "cancelable", "eventPhase");
}
}
}
This gets me the following behavior:
function testme(e:Event) {
trace(e);
}
test_mc.addEventListener(CustomEvent.REMOVED_FROM_STAGE, testme);
test_mc.dispatchEvent(new CustomEvent(CustomEvent.REMOVED_FROM_STAGE, 42));
//Traces [CustomEvent type="removedFromStage" data=42 bubbles=false cancelable=false eventPhase=2]
removeChild(test_mc);
//Traces [Event type="removedFromStage" bubbles=false cancelable=false eventPhase=2]
My goal is to get the custom data I want to pass to get passed from the event flash fires, not just the one that I fire. For example, what if I wanted to pass a movieclip along with a loader.COMPLETE event to put the resulting bitmap in?
You extended the Event class for it to dispatch with extra data, now if you want the Loader class to dispatch your custom event type, extend the Loader class to do that (or any other class you want to do this with). In this example I'll override URLLoader with this functionality (because Loader actually dispatches events from it's contentLoaderInfo, which needs two overridden classes, and I just want to keep it simple)
package com.net
{
import flash.net.URLLoader;
import flash.events.Event;
import com.events.CustomEvent;
public class CustomLoader extends URLLoader
{
// URLLoader already has a data property, so I used extraData
public var extraData:*;
override public function dispatchEvent(event: Event) : Boolean
{
var customEvent: CustomEvent = new CustomEvent(event.type, extraData, event.bubbles, event.cancelable);
return super.dispatchEvent(customEvent);
}
}
}
Now to use this with your CustomEvent class try this code in your .fla
import com.net.CustomLoader;
import com.events.CustomEvent;
var loader: CustomLoader = new CustomLoader();
loader.extraData = "Extra Data";
loader.load(new URLRequest("test.xml"));
loader.addEventListener(Event.COMPLETE, loadComplete);
function loadComplete(event: CustomEvent) : void
{
trace(event.data); // Extra Data
}
BAM! Custom data on your innately dispatched events!
The following shows the cleanest way to create a custom event. Typically event types have public static references typed in all capitol letters. When an event is dispatched, it passes an Event, or CustomEvent, object to the event handler method. This is where you can retrieve your passed value.
package com.hodgedev.events
{
import flash.events.Event;
public class CustomEvent extends Event
{
public static const VALUE_CHANGED:String = "VALUE_CHANGED";
public var value:Number;
public function CustomEvent(pValue:Number)
{
super(CustomEvent.VALUE_CHANGED);
value = pValue;
}
public override function clone():Event
{
return new CustomEvent(value);
}
}
}
When we dispatch events, we create a new instance of the event to be passed as such.
private var _someValue:int = 12;
dispatchEvent(new CustomEvent(_somevalue));