Flex key event listeners in class

advertisements

I have many buttons in Main.mxml. I'm trying to move the button functionality into a Class and have Event Listeners inside the class respond to Click and call other functions. I have written:

Main.mxml

<mx:Button x="23.5" y="10" label="checker" click="{goListen()}" />
<mx:Button id="btnT1" x="252.5" y="10" label="t1" />
<mx:Button id="btnT2" x="309" y="10" label="t2"/>
<mx:Button id="btnT3" x="366" y="10" label="t3"/>

Main.as

private function goListen():void
    {
        var t:ButtonListener = new ButtonListener(btnT1, btnT2, btnT3);
    }

ButtonListener.mxml

package com.util

{ import flash.events.EventDispatcher; import flash.events.MouseEvent;

import mx.controls.Alert;
import mx.controls.Button;

public final class ButtonListener extends EventDispatcher
{
    private var __btnArray:Array;

    public function ButtonListener(...btnList)
    {
        __btnArray = new Array();

        for each (var item:Button in btnList)
        {
            __btnArray.push(item);
        }

        buildListeners();
    }

    private function buildListeners():void
    {
        for each (var item:Button in __btnArray)
        {
            item.addEventListener(MouseEvent.CLICK, traceMe, false, 0, true);
        }
    }

    private function traceMe(event:MouseEvent):void
    {
        trace(event.target.label + " was clicked");
    }
}

}

so when I debug, I see the array filling up with the buttons, but the traceMe() function won't work. Not sure how I can get this to work. Or do I just have to have 30 event listeners and corresponding functions in the main class.


It looks like you have two different options or problems. If you change the last parameter in:

item.addEventListener(MouseEvent.CLICK, traceMe, false, 0, true);

to false, then everything should work because your event listener will stick around to handle the mouse clicks. Of courses, this means that if you click on your "checker" button a second time, you'll then have two sets of listeners responding to mouse clicks of buttons one, two, and three.

So, it's likely that the real solution you're interested in is leaving the line quoted above the same and instead changing the following line:

var t:ButtonListener = new ButtonListener(btnT1, btnT2, btnT3);

If you change the above line to store your button listener as a part of your class it will be available to respond to the mouse clicks, rather than having been garbage collected:

_buttonListener = new ButtonListener(btnT1, btnT2, btnT3);

That, of course, assumes that you have defined _buttonListener within an mx:script block:

<mx:Script><![CDATA[
    var _buttonListener:ButtonListener;
 ]]></mx:Script>

EDIT per comment:

In the code provided, t, the ButtonListener, goes out of scope. When it does, it is garbage collected unless you use strong references, which you do not per the last parameter in your addEventListener call.

Thus, make the button listener a member of the main class:

Main.mxml would then read:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
    <mx:Button x="23.5" y="10" label="checker" click="{goListen()}" />
    <mx:Button id="btnT1" x="252.5" y="10" label="t1" />
    <mx:Button id="btnT2" x="309" y="10" label="t2"/>
    <mx:Button id="btnT3" x="366" y="10" label="t3"/>
    <mx:Script>
        <![CDATA[
            private var _buttonListener:ButtonListener;

            private function goListen():void
            {
                _buttonListener = new ButtonListener(btnT1, btnT2, btnT3);
            }
        ]]>
    </mx:Script>
</mx:Application>

Since the event listener will no longer go out of scope, the weak references used by the event listeners will work as expected, being garbage collected when __buttonListener goes out of scope.