Search code examples
actionscript-3flashdevelop

click events don't reach root flash object



I started using as3 a while ago, and mostly used starling instead of native flash objects. Today I decided to give a try to raw flash, and created a simple button:

private var _button: SimpleButton;

public function Main() 
{
    if (stage) init();
    else addEventListener(Event.ADDED_TO_STAGE, init);
}

private function init(e:Event = null):void 
{
    removeEventListener(Event.ADDED_TO_STAGE, init);
    // entry point
    _button = new SimpleButton(new BUTTON); //BUTTON is an embedded bitmap
    addChild(_button);
    _button.useHandCursor = true;
    _button.addEventListener(MouseEvent.CLICK, OnClick);
}

private function OnClick(e:MouseEvent):void 
{
    trace("clicked");
}

This would definely work in starling, but I found that the click event won't dispatch to the button for some reason. Neither is hand cursor shown on mouse over. I tried mouse over, mouse up and other mouse events, but none of them work. I checked that the button is correctly added to stage. Also, when I add a mouse click event listener to the stage itself, clicks register normally. When I add a listener to Main, no events are registered again. I'm probably misunderstanding something obvious. Maybe I need to dispatch events manually down to the children? But that would be strage, though. Or can it be a bug in FlashDevelop? Please, help.


Solution

  • The constructor of SimpleButton takes 4 optional parameters:

    public function SimpleButton(upState:DisplayObject = null,
                                 overState:DisplayObject = null,
                                 downState:DisplayObject = null,    
                                 hitTestState:DisplayObject = null)`
    

    of which you supply the first one (upState):

    _button = new SimpleButton(new BUTTON); //BUTTON is an embedded bitmap
    

    The others default to null. That includes hitTestState which is the same as property of the class hitTestState:

    Specifies a display object that is used as the hit testing object for the button. [...] If you do not set the hitTestState property, the SimpleButton is inactive — it does not respond to user input events.

    It also includes a solution to your problem:

    For a basic button, set the hitTestState property to the same display object as the overState property.

    However, if all you want is to add click functionality to that Bitmap, which it doesn't have on its own, because it's not an InteractiveObject, simply use a Sprite:

    // entry point
    _button = new Sprite();
    _button.addChild(new BUTTON); //BUTTON is an embedded bitmap
    addChild(_button);
    _button.useHandCursor = true;
    _button.addEventListener(MouseEvent.CLICK, OnClick);
    

    Use SimpleButton only if you want the functionality of its 4 states.


    Please be careful with the overloaded term "stage":

    I checked that the button is correctly added to stage.

    If you mean the "drawing area" that you can see in the Adobe Flash IDE or the main time line with "stage", then yes, you'd be correct that your button is added to that.

    The stage property of DisplayObject however is something different. It's the top most element of the display list and the container that the instance of your Main class is added to, which happens at the start of the execution of your .swf in the FlashPlayer.

    As your Main class adds the _button to itself by calling its ownaddChild(), the button is added to the instance of Main and not stage, which are two different objects.