Monday, April 13, 2009

Rnadom Flex Note - Event handlers Nightmares

It is onerous to say the least to determine which events to handle for many objects.

 

For instance today, I was trying to get an <mx:HSLIDER> control to change the size of something in real time (as the thumb drags around)..

 

Let me explain how I figured out which one to use.

 

Here is how I started out:

 

<mx:HSlider id="mySlider" />

<mx:Text id="foo" text="{mySlider.value}"/>           

 

With this setup, there is some magic that occurs so that when you stop dragging the little thumb, the binding takes into effect and the value in the text box updates.  Easy enough, right?

 

So now, what if I want the value in “foo” to update AS I DRAG THE THUMB.  Should be possible (it is).

 

I counted, and there are no less than 63 events that an HSLIDER control can fire.  Which one to trap?

 

Well, not finding an obvious answer on the internet, I began attaching handlers to events that seemed to make sense:

 

So here is my first iteration:

 

<mx:HSlider id="mySlider" change="sliderChange(event)"/>

 

Notice that with Flex, you always have to pass in the (event) object. 

 

Now in your handler, you have to “handle” the specific type of event that has fired.

 

So let’s say I wrote my handler as follows:

 

    internal function sliderChange(event:StateChangeEvent) : void {

      var theSlider:Slider=Slider(event.currentTarget);

      foo.text = String(theSlider.value);

    }

 

THIS WILL NOT WORK AS I HAVE NOT USED THE RIGHT EVENT TYPE.

 

There are two ways to determine what type of event to put in your handler.

 

1)       put *something* and let the IDE tell you:

     “Error implicit coercion of a value of type mx.Events.SliderEvent to an unrelated type mx.Events.StateChangeEvent”

So, in this case, it’s telling you to use “SliderEvent”, not “StateChangeEvent”

2)       The second (preferred) way is to simply hover over the “event” part in your line:

<mx:HSlider id="mySlider" change="sliderChange(event)"/>

      *sometimes* a tooltip will appear telling you what event handler type to use

   3) A third way is to launch in debug mode, get an error and then you can hover over stuff and figure out what type of event handler to use:  See Screenshot:

 

 

One would think that this tells me the event type is SliderChange.

 

The actual event handler type is “SliderEvent”

 

The reason I am telling you all of this is that it is extremely frustrating to do some simply shit in the Flex IDE at the moment. Surely there must be a better way.

 

Anyway, moving on.

 

So now we have:

 

<mx:HSlider id="mySlider" change="sliderChange(event)"/>

 

And an event handler

    internal function sliderChange(event:SliderEvent) : void {

      trace(“sliderChange eventg fired”);

      var theSlider:Slider=Slider(event.currentTarget);

      foo.text = String(theSlider.value);

    }

By adding “trace” calls, when you run in debug mode, the text dumps to the console.

 

So, in this case, guess what?  This event does not fire until the user has released the thumbdrag handle!

 

So I try another event han dler

 

<mx:HSlider id="mySlider" currentStateChange="sliderStateChange(event)"/>

 

Notice I have to use a different handler because (you guessed it), the event fired is different.  So, going through the same agony as before, I determine that the event type being fired is, in fact, called “StateChangeEvent”. (Bascically by trying to run the app, letting it error out and reading the error message.

 

    internal function sliderStageChange(event:StateChangeEvent) : void {

      trace("sliderStageChange");

    }

 

Near as I can tell, this event does not fire.

 

So, thinking that it is not really the “slider” that is changing but the thumbdrag handle, I thought to add an event handler to that one as well:

 

Now, iteration #4:

 

        <mx:HSlider id="mySlider" thumbDrag="thumbDrag(event)" />

        <mx:Text id="foo" text="{mySlider.value}"/>           

 

And writing another event handler:

 

    internal function thumbDrag(event:SliderEvent) : void {

       trace("thumbDrag");

    }

 

 

I can see in my debug window that this is, in fact, the event that fires as you move the thumbDrag thingie around.

 

Therefore, I fix the event handler to read As follows:

    internal function thumbDrag(event:SliderEvent) : void {

       trace("thumbDrag");

      var theSlider:Slider=Slider(event.currentTarget);

      foo.text = String(theSlider.value);

    }

 

 

GUESS WHAT?  IT STILL DOESN’T WORK!

 

Turns out all you have to do is add “livedragging=”true” to the HSlider control and you do not have to write any event handlers.

 

 

So,

        <mx:HSlider id="mySlider" liveDragging="true"/>

        <mx:Text id="foo" text="{mySlider.value}"/>           

 

Does the trick..

 

 

Why do I tell you all about this?  So hopefully you can share in my pain and perhaps to learn something from my stupidity.

Flex is cool, but there is a pretty steep learning curve.

 

-shannon norrell