send dispatchEvent to child : example doesn't work? (flash, as3)

3.5k Views Asked by At

I'd like to send a dispatchEvent to a loaded swf, put into a movieclip. I found a good topic about it but my example doesn't work, the "trace" doesn't appear.

Edit.

  • I have a main.as
  • another class: submenu.as, that I import in main.as
  • when I click on the "main" menu in main.as, I would like to send a dispatchEvent to submenu.as (because I'd like the submenu to change one of its items, when I click on the "main menu" in main.as, so I need to send a dispatchEvent to submenu.as)
  • so I put a dispatchEvent in the method clickButton in my main.as: Event.CHANGE
  • and in the submenu.as, I'd like to listen to this event.CHANGE, and that's what I wrote below

End of edit.

In my parent class: each time I click on the menu:

dispatchEvent(new Event(Event.CHANGE));

or

stage.dispatchEvent(new Event(Event.CHANGE));

and in my child class :

public function initStage (e:Event){
[…]
this.parent.addEventListener(Event.CHANGE, switchItem, false, 0, true);

private function switchItem(pEvent:Event):void
{
    trace("PARENT_CHANGED");
}   

Any idea?

3

There are 3 best solutions below

6
On BEST ANSWER

As far as I can tell that topic doesn't apply too much to you, unless you actually are loading a swf at runtime and are trying to listen to events between them. I would also advise not using hierarchy on the display list for gathering references unless the hierarchy itself is indeed important. For example, maybe this menu removes itself from its parent container on close, or needs to add a displayObject to the same container its on, and doesn't care what the container is. Using hierarchy forces you to maintain that hierarchy for the references, which can sometimes make it hard to make changes on a growing application. Heres an example of what you may be looking for that doesn't use the display list to gather references:

public class Main extends Sprite 
{
    private var menu:SubMenu;

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

    private function init(e:Event = null):void 
    {
        removeEventListener(Event.ADDED_TO_STAGE, init);
        menu = new SubMenu(this);
        addChild(menu)  //This is not neccessary for them to communicate
        dispatchEvent(new Event(Event.CHANGE));
    }

}

public class SubMenu extends Sprite
{
    private var mainMenu:IEventDispatcher;  //This could be typed as Main instead of IEventDispatcher if needed. 
                                            //Sprites are however IEventDispatchers

    public function SubMenu(mainMenu:IEventDispatcher) 
    {
        this.mainMenu = mainMenu;
        mainMenu.addEventListener(Event.CHANGE, switchItem, false, 0, true);
    }

    private function switchItem(event:Event):void
    {
        trace("Parent_Changed")
    }
}

Heres an example using the display list hierarchy (I wouldn't recommend it) :

public class Main extends Sprite 
{
    private var menu:SubMenu;

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

    private function init(e:Event = null):void 
    {
        removeEventListener(Event.ADDED_TO_STAGE, init);
        menu = new SubMenu();
        addChild(menu)  //This is neccessary, and the menu cannot be added to a different parent

        dispatchEvent(new Event(Event.CHANGE));

    }
}
public class SubMenu extends Sprite
{

    public function SubMenu() 
    {
        //Neccessary because submenu will not have a parent when its first instantiated.
        //When its on the stage then you can have it grab its parent and add a listener.
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);

    }

    private function init(event:Event = null):void
    {
        removeEventListener(Event.ADDED_TO_STAGE, init);

        //Parents available
        parent.addEventListener(Event.CHANGE, switchItem, false, 0, true);
    }

    private function switchItem(event:Event):void
    {
        trace("Parent_Changed")
    }

}
1
On

From the child SWF, access from loaderInfo.

loaderInfo.sharedEvents.addEventListener(Event.CHANGE, switchItem, false, 0, true);

Based upon your edits, it sounds like main.as and submenu.as are both in the same SWF, and maybe the issue is that you're trying to bubble events down?

You can dispatch the event against the child object, or use some static / singleton pattern, such as:

public static var dispatcher:IEventDispatcher = new EventDispatcher();

Dispatch events against the dispatcher, and listen for events in the dispatcher.

This is similar to how you are attempting to dispatch events against the stage; however, the child must listen against the stage and not "this.parent". I wouldn't recommend that.

Otherwise, have the parent pass the event to the child as in main.as dispatch event against child instance defined by submenu.as.

1
On

I see two likely possibilities.

First, try adding a breakpoint or tracing what this.parent is set to in your initStage() function. If you are saying dispatchEvent() or stage.dispatchEvent() but the child is actually added to an object within Main rather than to the instance of Main itself, then it's probably listening to the wrong object for the event.

Second, make sure that initStage() is actually executing before your event is fired. It's possible that the listener isn't set at the time that the event is dispatched.