I would like to assign an event listener to a protected timer variable in the parent class.
I am working with Adobe LCCS, and created a BatonProperty
which implements Baton
Now, Baton has a protected timer variable declared like this, and for some reason, I am unable to get access to this _autoPutDownTimer, from a BatonProperty instance.
public function Baton()
{
super();
_autoPutDownTimer = new Timer(_timeout*1000, 1);
_autoPutDownTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
invalidator.addEventListener(Invalidator.INVALIDATION_COMPLETE,commitP roperties);
}
I would love to attach an eventlistener to it like this, but it seems I cannot, any tips are truly appreciated:
public var mybatonprop:BatonProperty;
mybatonprop= new BatonProperty();
mybatonprop.sharedID = "myBaton";
mybatonprop.subscribe();
mybatonprop.baton._autoPutDownTimer.addEventListener(TimerEvent.TIMER,countDown);
This gives the error : "actionscript attempted access of inaccessible property through a reference with static type" But it seems that property is not private, only protected, since it is declared like this
/**
* #private
*/
protected var _autoPutDownTimer:Timer;
If BatonProperty extends Baton, then just change the line:
mybatonprop.baton._autoPutDownTimer.addEventListener(TimerEvent.TIMER,countDown);
to
mybatonprop._autoPutDownTimer.addEventListener(TimerEvent.TIMER,countDown);
otherwise, make _autoPutDownTimer public, or follow #Jacob's answer.
Or for a third suggestion, as Baton is an Adobe class and you can't edit it, create your own class MyBaton which extends Baton, then do either of the two suggestions. (MyBaton will work everywhere Baton does)
protected means private except to descendants of the class. i.e. classes that inherit from the parent. It looks like your BatonProperty uses Baton via composition, not inheritance. And, from what I can tell, it seems like you're trying to access the _autoPutDownTimer from Baton/BatonProperty via a third class.
My recommendation, though would not be to add the event listener directly to the timer, but to dispatch an event from Baton in the onTimerComplete function
protected function onTimerComplete(event:TimerEvent):void {
....
dispatchEvent(new Event('putDownComplete'));
}
and
mybatonprop.baton.addEventListener('putDownComplete', onPutdownComplete);
Related
I'm creating an application using Flex 4.
When the app is started, it reads a XML file and populate objects. The .send() call is asynchronous, so I would want to listen/watch to this populated object, and when it has finished, dispatch an event for other classes, so they can use it.
package model{
public class LectureService extends HTTPService{
[Bindable]
private var _lecture:Lecture;
...
}
The xml is parsed correctly and loaded inside the object lecture of the class Lecture.
If I use the MXML notation in the main.mxml app, it works fine (the object is used when the it is populated after the async request):
<mx:Image id="currentSlide" source={lectureService.lecture.slides.getItemAt(0).path} />
BUT, I have another ActionScript class and I'm not able to listen to this dispatched (by [Bindable]) event.
package components{
public class LectureSlideDisplay extends Image
{
public function LectureSlideDisplay()
{
super();
this.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, onChangeTest);
}
private function onChangeTest(e:PropertyChangeEvent):void {
trace('test');
}
I have already tried:
using (like above) addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, methodName).
tried to change the [Bindable] to [Bindalbe("nameEvent")] and listen for this, nothing.
using CreateWatcher method, doesn't work.
tried to have a look to the generated code of the class, but didn't help me
if (this.hasEventListener("propertyChange")){
this.dispatchEvent(mx.events.PropertyChangeEvent.createUpdateEvent(this, "lecture", oldValue, value));
}
How can I listen and have the populated object in another class?
Maybe the problem is that I'm listening from another class, but in this case how can I implement this?
It seems the event is dispatched, but I can't listen to it.
For who wants the answer, I have resolved changing the addEventListener object.
It is not right to use:
this.addEventListener(...)
Use instead:
lectureService.addEventListener(...)
I have changed my code to listen to this event in the main app MXML, and then inside the handler method, call the public method of your components to use the new data.
You can't solve all your problems by just extending the class. You should really look into Commands for your HTTP requests.
The change property event is used internally for watchers and won't dispatch in the overall component. What you want to do for your LectureSlideDisplay is to override the source setter. Every time it is called, a new value is being binded to it:
package components{
public class LectureSlideDisplay extends Image
{
override public function set source(value:Object):void
{
super.source = value;
// do whatever
}
public function LectureSlideDisplay()
{
super();
}
}
}
You should really read up on how Binding works.
Consider to use BindingUtils class. You can found documentation here. And a couple of usage samples: one, two.
I'm trying to override a subclass's method but I think I need access to the superclass one higher up in the hierarchy. So I'd like to do something like super.super.methodName();
FYI, the actual problem I'm trying to solve should be explained by my code below:
public class A extends UIComponent{
override protected function keyDownHandler(event:KeyboardEvent):void{
super.keyDownHandler(event);
if(event.keyCode==46)
remove();
}
}
public class B extends A{
override protected function keyDownHandler(event:KeyboardEvent):void{
if(event.keyCode==46 && removeable==true)
remove();
else
super.super.keyDownHandler(event);
}
}
If I use the class A's KeyDownHandler method, you will see that remove() is called regardless. However, the docs state that I need to call UIComponent.keyDownHandler whenever I subclass UIComponent. Of course this works for the first subclass, but not that subclass's subclasses.
I realise that I could put the functionality all into A with something like
if(this is B){...}
but that seems to me to be a hack.
You could add another method to class A, let's call it superKeyDownHandler whose only purpose would be to call some method from superclass.
protected function superKeyDownHandler(event:KeyboardEvent):void{
super.keyDownHandler(event);
}
And then what you want to achieve would be as easy as calling
super.superKeyDownHandler(event);
This is just a way around however not the actual clean solution, so use it at your own risk :)
UPDATE:
Something maybe cleaner would involve overriding keyDownHandler content of class A. So in class A you would have:
public class A{
override protected function keyDownHandler(event:KeyboardEvent):void{
super.keyDownHandler(event);
overridableContent();
}
protected function overridableContent(){
//do class A specific things here
if (event.keyCode==46)
remove();
}
}
public class B extends A{
override protected function overridableContent(){
//do class B specific things here
if (event.keyCode==46 && removeable==true)
remove();
}
}
Calling something like new B().keyDownHandler(event) now will cause calling keyDownHandler as it is defined in class A with content taken from class B.
What I gather from your question is that, you want to use the functionality given by the superclasses' superclass, and not by the superclass itself.
Am I right cammil?
I have a flex app with lots of nested views and popup windows..
I'd love to catch all the CHANGE events in the application at the top level.. all of them, simply to notify the user that he has changed something (trust me it makes sense in my app).
Now, I tried to add an event listener in the Application creationComplete handler like this:
private function init():void {
this.addEventListener(flash.events.Event.CHANGE, function f():void {...})
}
but it does not work.. why? I read in the docs that event bubbling for the CHANGE event is set to false before dispatching. How can I change that? Is there any other way to achieve my goal?
thanks
Try listening to events on the SystemManager instead of the Application. As far as I understand, SystemManager sits at the very top of the display list, adding the application, popups and other UI entities as children.
In Flex 3 and below, you can retrieve it via Application.application.systemManager.
Read more on the SystemManager on Deepa's blog:
http://iamdeepa.com/blog/?p=11
I am also having trouble with a group of TextArea controls where I would like to listen for the change event on their container (parent) instead.
What I did in the end was to extend the TextArea class and create a listener for the change event. From the listener I would then dispatch a custom event that could bubble.
public class BubblingTextArea extends TextArea
{
public function BubblingTextArea()
{
super();
addEventListener(TextOperationEvent.CHANGE, changeHandler);
}
private function changeHandler(event:TextOperationEvent):void
{
dispatchEvent(new ChangeBubbleEvent(ChangeBubbleEvent.BUBBLE_CHANGE));
}
}
The custom event:
public class ChangeBubbleEvent extends Event
{
public static const BUBBLE_CHANGE:String = "bubbleChange";
public function ChangeBubbleEvent(type:String, bubbles:Boolean=true, cancelable:Boolean=false)
{
super(type, bubbles, cancelable);
}
}
I am sure someone can come up with a more elegant solution since I am still quite new to Flex and AS3 myself.
As far as I know, PopUps happen outside of the Application's main displayList, so that's probably why you're not seeing bubbling. In this case, you'll need to manually add listeners to popups. The Flash change event does bubble according to the docs: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/events/Event.html#CHANGE
I personally like to use a framework such as RobotLegs or Parsley.
The basic idea is that each view and popup gets a mediator. The mediator's job is to communicate between the view and the command/model. Those mediators can listen directly to the view and the view's components.
I am working in air application , i need to know how to add event listener when any object is updated, how can i implement this.
Example: i have Class name Vehicle, and child class are Car,Bus,Bikes,Scooter,..etc, child class also have many properties like color,model no,....etc
I have array collection and AddChild() method in Vehicle class by this, i will add, child class to the vehicle class.
I need a event listener which can trigger if any of the property is updated or changed in any of the child class property, how can i implements this in Flex3.
I need this for knowing, is there any update happen in the Object.
Thanks In Advance
One thing you can do is to make getters and setters for the properties instead of public vars and have your class extend EventDispatcher, if it does not already do so because it is extended from a MovieClip, like:
private var _vehicleName:String;
.
.
.
public function set vehicleName(value:String):void {
_vehicleName = value;
dispatchEvent(new VehicleEvent(VehicleEvent.propertyChange, "vehicleName"));
}
public function get vehicleName():String {
return _vehicleName;
}
(VehicleEvent being an extended class of Event with an extra string to signify which property changed)
Then you can add an eventlistener to the vehicles and they will dispatch events when the properties defined in this way change.
If you use an Array Collection for the vehicles and if you make the properties of the vehicles Bindable as Amarghosh suggests, then the array collection already should throw an Collection Event of the kind UPDATE. It also tells you which items (Vehicles) were updated an afaik also which properties were updated. But in general it is easier to directly bind to the property, like Amarghosh says.
I'm experimenting with TextArea and inheritance to implement some additional functionality on the protected textField property.
Unfortunately, when I create a new instance of the subclass, this property is set to null. I'm probably misunderstanding the way super() works, but I thought it would have been instantiated after the constructor finished.
Here's a small snippet of code which extends TextArea:
public final class ExtTextArea extends TextArea {
public function ExtTextArea() {
super();
}
public function testTextField():void {
if (textField == null)
Alert.show("null!");
}
}
}
The invoking code is simple:
var extTextArea:ExtTextArea = new ExtTextArea();
extTextArea.testTextField();
The Alert in ExtTestArea appears every time I run this code.
Why is this? Is there something more I need to do to access the textField property?
Since textField is "the internal UITextField that renders the text of this TextArea" I believe it will remain null until you add it to the display via .addChild(...). I ran a quick test to verify that once I've added it to the display, it is no longer null. You might want to add an event handler to the "creation complete" event and adjust it at that point (I think).
The Flex SDK comes with source code, so you can take a peek and see when this field is initialized. It is not initialized in the constrcutor, but you will see that a new TextField instantiated by createChildren(), which is called when the component is added to a layout container.