0

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?

Community
  • 1
  • 1
Paul
  • 6,108
  • 14
  • 72
  • 128
  • It's somewhat unclear what you're referring to with "parent" and "child" since you start by talking about parent and child swfs but then later talk about parent and child classes. I'm thinking you mean that the child class is the document class of the child swf, but I'm not sure. Can you clarify? – HotN Oct 15 '11 at 21:56

3 Answers3

1

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.

Jason Sturges
  • 15,855
  • 14
  • 59
  • 80
  • thanks, but it changes nothing : are you sure to start with loaderInfo ? i've got no error, and when i click on the menu, it should launch a trace but nothing appears in the console – Paul Oct 16 '11 at 12:15
1

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")
    }

}
Mike McFarland
  • 657
  • 4
  • 17
  • thanks i really appreciate, i've got a question here : `menu = new SubMenu(this);`: i actually "load" my submenu, i've got a submenu.fla and submenu.as, so i'm loading it using `URLRequest` etc. and i've got a "loader" that i put into a movieclip. how can i implement "this" as a parameter? in your example, it looks like a movieClip exported to as3 in the `main`'s fla ? Thanks – Paul Oct 17 '11 at 13:21
  • I didn't realize you actually were using a Loader. This complicates things, and unless you have a good reason to load swfs inside swfs I wouldn't. If you need to load content dynamically I would go the route of loading assets instead (images/videos/xml/swfs with display symbols), but try to avoid loading in programs inside programs. The reason being if you use the same class in both swfs, unexpected problems can occur unless you understand how application domain works, and there's more overhead. As well as having to compile two programs to rebuild your application. There are exceptions to this – Mike McFarland Oct 17 '11 at 16:09
  • So, you can't send parameters to the constructor of the swf your loading (since you don't actually get to instantiate it, it already is once the loader has finished retrieving it). So you have a few options, you can retrieve the child from the parent via the loader using its content property (and then cast it as your child type) and set a property. You can use hierarchy and remember that the childs parent is the loader, and the loaders parent is the main class. Or you can dispatch and listen to events on the sharedEvents dispatcher on the loaderInfo (accessible on the loader for the parent) – Mike McFarland Oct 17 '11 at 16:16
  • thanks, but i'm a bit confused! your 1st point: after `event.complete` should i use something like e.target.loaderInfo.content, then cast it in `Loader`? and, let's say the property is `mainMenu`, i can do the same as above in your example: `mainMenu.addEventListener` and it will recognise it? your 2nd point: i don't understand it, your 3d point: when the loader is complete, i use `e.target.loaderInfo` but then i'm a bit lost with sharedEvents. `Jason`answered me something like that, but for what i understood, the loaderInfo.sharedEvents in "submenu.as" did not work – Paul Oct 17 '11 at 17:07
  • For two objects to communicate with events you need to be listening and dispatching from the same eventDispatcher (with the exception of bubbling/use capture events). From Main it would be: `loader.contentLoaderInfo.sharedEvents.dispatchEvent(...)` assuming that loader was used to load the subMenu SWF. From the subMenu it would be `loaderInfo.sharedEvents.addEventListener(...)`. Then both swfs will working with the same eventDispatcher. I still advocate not using separate swfs unless needed though. – Mike McFarland Oct 19 '11 at 18:10
  • yeah thanks, i created movieclips directly in the fla, i did not have time to fix all the bugs ;) thanks for your help – Paul Oct 21 '11 at 12:55
1

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.

HotN
  • 4,216
  • 3
  • 40
  • 51
  • thanks HotN, so `this.parent` gave me `[Object loader]`, because i load the submenu.swf with URLRequest etc. so i tried to link the two of them : `loader_submenu.dispatchEvent(new Event(Event.CHANGE));`, but i still don't have the `trace` from my submenu.swf – Paul Oct 17 '11 at 13:49