Actionscript 3.0 -> How to override a protected method from UIComponent - apache-flex

I want to create a custom button in ActionScript.
This is my code:
import flash.events.MouseEvent;
import mx.controls.Alert;
import spark.components.Button;
public class BookViewButton extends Button
{
public function BookViewButton()
{
super();
}
override protected function mouseOver(event:MouseEvent,increase:int,newImageSource:String):void{
Alert.show("mouseOver for new class works");
}
}
But Adobe Flash Builder signals the method overriding line as an error.
I tried to change the new method signature so that it would match exactly, like this: (I thought the error might be because I was adding extra parameters to the mouseOver function so Flex might have not recognized it as an overriding)
override protected function mouseOver(event:MouseEvent):void{
Alert.show("mouseOver for new class works");
}
But still it doesn't work. Same little red exclamation mark comes up to signal a mistake.
I'd greatly appreciate any help. Thanks.

What SDK version do you use if you have mouseOver() method in Spark Button hierarchy?
Spark button has mouseEventHandler() method to override:
override protected function mouseEventHandler(event:Event):void
{
super.mouseEventHandler(event);
var mouseEvent:MouseEvent = event as MouseEvent;
if (event.type == MouseEvent.ROLL_OVER)
{
// My roll over logic here
}
}
And it is better to post the error text which IDE gives you. To copy it just open Problems view in Flash Builder, found your error message and copy it via context menu.

You can't use override here because the base class Button does not have a method mouseOver to override.
If you remove the override keyword it should work fine. That said, you'll need to actually add a listener for your function for it to be called when you mouse over. Like this:
import flash.events.MouseEvent;
import mx.controls.Alert;
import spark.components.Button;
public class BookViewButton extends Button
{
public function BookViewButton()
{
addEventListener(MouseEvent.MOUSE_OVER, _mouseOver);
}
private function _mouseOver(event:MouseEvent):void
{
Alert.show("mouseOver for new class works");
}
}
Info on super();
There's no need to call super in the constructor of an extending class, unless there are arguments that you want to parse. Example.
package
{
public class A extends Object
{
public function A()
{
trace("A");
}
}
}
And the extending class:
package
{
public class B extends A
{
public function B()
{
trace("B");
}
}
}
If we do:
var thing:B = new B();
You will have the output:
A
B
However, if you wanted arguments for your constructor, you would need to parse them up to the constructor of the class you're extending using super(). Like so:
public class A extends Object
{
public function A(arg:String)
{
trace(arg);
}
}
public class B extends A
{
public function B(arg:String)
{
super(arg);
}
}
Now this will output "asdf":
var thing:B = new B("asdf");

Related

flexunit of handle customer event and Async.asyncHandler()

Any one know how does Async.asyncHandler() work and if Async.processOnEvent() can only used in [Before] method.(Any one know some helpful document besides http://docs.flexunit.org/).
I define a MXML component named HelloCompo(extends Vbox), and the component define a function named hello(), in the hello() dispacthed a customer event named HelloEvent(the event type just named "hello"), and in another function named init() listened for the event, I want to test whether the event is dispatched properly or not. So I have the test following:
var helloCompo = new HelloCompo();
helloCompo.hello();
helloCompo.addEventListener("hello", Async.asyncHandler(this, handleHello, 1000, null, handleTimeOut));
The test will always excute the handleTimeOut method(means the HelloEvent is not dispatched, but when helloCompo.hello() excute, it really dispacthed, so what's going wrong?)
package flexUnitTests
{
import flash.events.Event;
import org.flexunit.asserts.assertTrue;
import org.flexunit.asserts.fail;
import org.flexunit.async.Async;
public class HelloTest
{
private var helloCompo:HelloCompo;
[Before]
public function setUp():void
{
helloCompo = new HelloCompo();
}
[After]
public function tearDown():void
{
helloCompo = null;
}
[Test(async)]
public function testHello():void
{
var handler:Function = Async.asyncHandler(this, helloHandler, 300, null, helloFailed);
helloCompo.addEventListener("hello", handler);
helloCompo.hello();
}
private function helloHandler(event:Event, passThroughObject:Object):void
{
//assert somthing
}
private function helloFailed(event:Event, passThroughObject:Object):void
{
fail("hello not dispatched");
}
}
}
HelloCompo.as
package
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
public class HelloCompo extends EventDispatcher
{
public function HelloCompo(target:IEventDispatcher=null)
{
super(target);
}
public function hello():void
{
dispatchEvent(new Event("hello"));
}
}
}
I think you need to add your event listener before calling hello() actually

Flex Event Dispatcher Questions

I am trying to dispatch an custom YouTubeEvent from my Player.as and wish my Main.as would listen and create the video player...Apparently my eventHandler can't catch the event to create the videoplayer.......My flex debug mode is so screw up I can't even use it...My code is as follow..I really appreciate any reply or help.....
My custom event..
package com.youtube.events {
import flash.events.Event;
public class YouTubeEvent extends Event{
public static const PLAYER_READY:String="PLAYER_READY";
public function YouTubeEvent(type:String){
super(type);
}
}
}
My Main.as
public class SearchYoutube extends Sprite
{
private var videoPlayer:Player;
public function SearchYoutube()
{
/*********************Load Video Player****************************/
loadPlayer();
}
private function loadPlayer():void{
videoPlayer= new Player();
videoPlayer.addEventListener(YouTubeEvent.PLAYER_READY, playerReady);
//playReady would never be excuted....
}
private function playerReady(event:YouTubeEvent):void{
videoPlayer.createPlayer(); //This handler would never be executed...
addChild(videoPlayer); //This handler would never be executed...
}
}
Player.as
//only show part of codes here
public function Player(){
}
public function createPlayer():void{
_loader = new Loader();
_loader.contentLoaderInfo.addEventListener(Event.INIT, onLoaderInit);
}
private function onLoaderInit(event:Event):void {
_loader.content.addEventListener("onReady", onPlayerReady);
}
private function onPlayerReady(event:Event):void {
dispatchEvent(new YouTubeEvent(YouTubeEvent.PLAYER_READY));
}
YouTubeEvent.PLAYER_READY is dispatched some time after calling createPlayer(). You should call createPlayer() after videoPlayer.addEventListener(YouTubeEvent.PLAYER_READY, playerReady):
private function loadPlayer():void
{
videoPlayer= new Player();
videoPlayer.addEventListener(YouTubeEvent.PLAYER_READY, playerReady);
videoPlayer.createPlayer();
}
This short tutorial will get you on the right path on using custom events with Flex.

AS3: Event dispatching via dispatchEvent- pass params?

I would like to dispatch an event from my class along with a url.
I know that I can do the following:
import flash.events.EventDispatcher;
private function thumbClick(e:MouseEvent):void
{
dispatchEvent(new Event("clicked"));
}
But I don't know how I would send params along with the event...?
Also, in my main app runner, I try:
var my_ev:Event = new Event("clickedImage");
my_ev.hasOwnProperty(e.currentTarget.link);
dispatchEvent(my_ev);
...but I'm not sure that this would be the correct syntax.
Thanks for any help,
jml
Allan is correct, you will want to make a custom event. Couple of things to note:
import flash.events.Event;
public class ThumbnailEvent extends Event
{
public static var THUMB_CLICKED:String = "thumbClicked";
private var _url:String;
public function get url():String { return _url }
public function ThumbnailEvent (type:String, url:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type,bubbles,cancelable);
_url = url
}
override public function clone():Event
{
return new ThumbnailEvent(type, url, bubbles, cancelable);
}
}
Custom events need to always override clone. If the event is bubbled or relayed in anyway it needs this method. Custom properties should be private with a read-only getter. This is a standard convention to prevent the alteration of properties throughout the life of the event.
Using this approach would change your code to:
private function thumbClick(e:MouseEvent):void
{
dispatchEvent(new ThumbnailEvent(ThumbnailEvent.THUMB_CLICKED, myUrlString));
}
//elsewhere
addEventListener(ThumbnailEvent.THUMB_CLICKED, thumbClickedHandler);
private function thumbClickedHandler(event:ThumbnailEvent):void
{
var link:String = event.url;
}
Custom Event tutorial at adobe.com
I just make a custom event class.
import flash.events.Event;
public class ThumbnailEvent extends Event
{
public static var THUMB_CLICKED:String = "thumbClicked";
public var url:String;
public function ThumbnailEvent (type:String,url:String)
{
super(type);
this.url = url
}
}
and then use it like:
var thumbEvent:ThumbnailEvent = new ThumbnailEvent(ThumbnailEvent.THUMB_CLICKED,"myURL");
dispatchEvent(thumbEvent);

Querying the state of a class's listener

I have instantiated a class (class1) that loads some data via PHP in an AS3 Flex project.
I instantiate class1, which is asynchronous and utilizes a URLLoader() to obtain its data.
Then I would like to instantiate class2, which needs to USE the data from class1, but when I simply instantiate it I find that class1's instance variable is not populated yet because I am calling class2 too quickly.
How can I create such a dependency that will link correctly?
I am really new to using listeners, but I am imagining a listener in class2 might be what I need?
Or maybe I can pass a reference to the listener in class1 into class2?
I also know nothing about dispatching events... is this the key?
Here's an example in pseudo code:
var class1:myC1 = new myC1("http://some/url/to/utilize");
//this never shows up because it hasn't loaded at the time i request it
trace("the stuff from class1 is: ", class1.myXMLList);
//and of course i can't use it here either
var class2:myC2 = new myC2(0x000000, class1.myXMLList);
Thanks for any help,
jml
Based on your question, I'm posting this "pseudo code" hopping it will help
package {
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.*;
public class Class1 extends EventDispatcher {
private var _loader:URLLoader;
public var data:XMLList;
public function Class1(url:String) {
_loader = new URLLoader();
_loader.addEventListener(Event.COMPLETE, completeHandler);
// rest of the code here ....
_loader.load(new URLRequest(url));
}
protected function completeHandler(event:Event):void {
data = new XMLList(_loader.data); // probably wrong but
// I figured you had already
// implemented this part
dispatchEvent(new Event(Event.COMPLETE));
}
}
}
I figured class 2 might look like this
package {
public class Class2 {
// your stuff here
public function Class2(color:uint, data:XMLList) {
}
}
}
The main class
package {
import flash.display.Sprite;
import flash.events.Event;
public class Main extends Sprite {
public var c1:Class1;
public var c2:Class2;
public function Main() {
c1 = new Class1("http://some/url/to/utilize");
c1.addEventListener(Event.COMPLETE, completeHandler);
}
protected function completeHandler(event:Event):void {
c2 = new Class2(0xffcc00, c1.data);
}
}
}
Hope this helps
If you want Flex/FlashBuilder to autocomplete the events for your classes, you can use the "Event" metadata tag before your class definition. Based on the example above, it would look like this
package {
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.*;
// use the "Event" metadata tag
[Event(name="complete", type="flash.events.Event")]
public class Class1 extends EventDispatcher {
private var _loader:URLLoader;
public var data:XMLList;
public function Class1(url:String) {
_loader = new URLLoader();
_loader.addEventListener(Event.COMPLETE, completeHandler);
// rest of the code here ....
_loader.load(new URLRequest(url));
}
protected function completeHandler(event:Event):void {
data = new XMLList(_loader.data);
dispatchEvent(new Event(Event.COMPLETE));
}
}
}
Now FlexBuilder/FlashBuilder should "autocomplete" the events for that class.
The downside is that you can't use "constants" with the "Event" metadata tag so this :
[Event(name=Event.COMPLETE, type="flash.events.Event")]
wouldn't work.
You can read more about event/event dispatching here.
Hope that helps :)

Custom Event Not Captured- why?

I am having a problem where I dispatch a custom event but the listener does not receive it (i.e. myHandler() in the code below). If I put everything in one mxml file, it works. When I separate the responsibilities in to separate classes, it fails. It is not clear to me what I am missing.
Any help you be appreciated.
Here is my code (update() in ViewModel.as is the entry point):
ChangeEvent.as
import flash.events.Event;
public class ChangeEvent extends Event
{
public function ChangeEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
// Set the new property.
this.isEnabled = isEnabled;
}
// Define static constant.
public static const ENABLE_CHANGED:String = "enableChanged";
// Define a public variable to hold the state of the enable property.
public var isEnabled:Boolean;
// Override the inherited clone() method.
override public function clone():Event {
return new ChangeEvent(type, isEnabled);
}
}
Model.as
public class Model extends EventDispatcher
{
private function TriggerEvent():void
{
var eventObj:ChangeEvent = new ChangeEvent(ChangeEvent.ENABLE_CHANGED);
dispatchEvent(eventObj);
}
}
ViewModel.as
public class ViewModel
{
import mx.controls.Alert;
import ChangeEvent;
private var model:Model;
public function ViewModel()
{
model = new Model();
addEventListener(ChangeEvent.ENABLE_CHANGED, myHandler);
}
public function update():void {
model.LoadData();
}
private function myHandler(event:Event):void {
Alert.show("An event occurred.");
}
}
Do I have to 'register' the event in ViewModel.as similar to the metadata tag in mxml?
e.g.
[Event(name="enableChange", type="ChangeEvent")]
You have to add the event listener on the model object (since it is the one dispatching the event).
model = new Model();
model.addEventListener(ChangeEvent.ENABLE_CHANGED, myHandler);
Hope that helps.

Resources