views:

194

answers:

3

I tried to dispatch a custom event from some component on the stage and I registered another component to listen to it but the other component doesn't get the event.

Here is my code; what did I miss?

public class Main extends MovieClip //main document class
    {
        var compSource:Game;
        var compMenu:Menu;

        public function Main() 
        {
            compSource = new Game;
            compMenu = new Menu();
            var mc:MovieClip = new MovieClip();
            addChild(mc);
            mc.addChild(compSource); // the source of the event - event dispatch when clicked btn
            mc.addChild(compMenu);  //in init of that Movie clip it add listener to the compSource events
        }

    }


public class Game extends MovieClip 
    {
        public function Game() 
        {
            btn.addEventListener(MouseEvent.CLICK, onFinishGame);
        }

        private function onFinishGame(e:MouseEvent):void 
        {

            var score:Number = Math.random() * 100 + 1;
            dispatchEvent(new ScoreChanged(score));
        }


    }

public class Menu extends MovieClip
    {
        //TextField score
        public function Menu() 
        {
            addEventListener(Event.ADDED_TO_STAGE, init);
        }   

        private function init(e:Event):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
//on init add listener to event ScoreChanged
            addEventListener(ScoreChanged.SCORE_GAIN, updateScore);
        }

        public function updateScore(e:ScoreChanged):void 
        {
//it never gets here!
            tScore.text = String(e._score);
        }   

    }



public class ScoreChanged extends Event
    {
        public static const SCORE_GAIN:String = "SCORE_GAIN";
        public var _score:Number;

        public function ScoreChanged( score:Number ) 
        {
            trace("new score");
            super( SCORE_GAIN, true);
            _score = score;
        }
}

I don't want to write in Main

compSource.addEventListener(ScoreChanged.SCORE_GAIN, compMenu.updateScore);

because I don't want compSource knowing about compMenu; it's compMenu's responsibility to know what events it needs to listen to.

A: 

Game and Menu appear to be on different chains in the chain of events. Events bubble upwards and since Game and Menu are siblings they will not have access to each other's events.

One solution would be for you to send reference of the game to the menu from the main screen. Then add an event listener to it from the menu at that point.

Sandro
A: 

Sandro is correct, because events bubble up, not sideways, your Menu will never see the event.

A possible solution: as Main already "knows" about both compSource and compMenu you can safely pass the event through your main class:

class Main{
    public function Main() 
    {
        compSource = new Game();
        compSource.addEventListener(ScoreChanged.SCORE_GAIN, scoreGainHandler);
        compMenu = new Menu();
        //... rest of constructor
    }

    public function scoreGainHandler(event:ScoreChanged):void
    {
        compMenu.updateScore(event);
    }
    //... rest of class

This way your Game and Menu stay independent.

In fact, if you build it this way, Menu doesn't need to listen to a score change event at all, you can just change the update function to take a score variable:

class Menu{

    public function updateScore(score:int):void 
    {
        tScore.text = String(score);
    }
    //... etc
Reuben
A: 

wow this clear things very well! Thanks for that. I don't underst why event is implemented like this in action script3 why dispatch event, only dispatch up the display list and don't send the event to any component that done the registration of the listener to this certain event.

its not logic to me that event depends on hierarchy and containment of the display list objects.

what is that logic behind implementing that kind of event model what do i miss here?

Shay
It seems you are expecting events to be global, where in AS3 they depend on either the display list hierarchy (for UI events), or explicitly setting listeners using addEventListener - this is actually really useful - by making it explicit which objects are listening to which it helps stop unexpected behaviour in your application.(PS - if one of our answers was helpful, please mark it as correct)
Reuben