Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

[noob] Help understanding why event listener continues even after removal...

Explorer ,
Feb 18, 2014 Feb 18, 2014

Hey once again,

I'll try to do my best to explain. I can get this to work correctly, but I'd like to understand why what I was doing earlier wasn't working.

I'm having a little trouble understanding why an event listener continues listening even after I remove it. I have a set-up where, a Parent MovieClip ("CampScene") is established, and an event listener is added to listen for a function ("walkUpToCampfire") to see if a condition is true ("comingFromAx == true", which won't be true until later).

If it is true, an animation plays, an event listener is added to see if the animation is done, and if it is an event listener is added to listen for a click ("campScene.goToAx") for a new animation to play and other events to occur. (It won't be set to true until later.)

If it isn't true (which is the situation I'm working with initially), the event listener told to listen for a click on "campScene.goToAx" is set up immediately. The function that follows removes the event listener, thus it's suppose to stop listening for a click and let an animation play all the way through.

The problem is a click continues to be listened for, and if one keeps clicking the animation restarts each time, which is what I don't want to happen.

--------------------------------------

I'm able to solve the problem by adding the line "campScene.removeEventListener(Event.ENTER_FRAME, walkUpToCampfire);" or by setting mouseEnabled to false for "campScene.goToAx", but I'm trying to understand what is going on.

Is it, even though I'm removing the ("campScene.goToAx") listener in one function ("goToAxScene"), "campScene.addEventListener(Event.ENTER_FRAME, walkUpToCampfire);" continues to listen for a mouse click unless it is removed also?

Again, I'm just trying to understand how this is working.

--------------------------------------

This should be all the relevant AS. Naturally, let me know if more information is needed. (I can post the FLA/AS files if need be.)

public function practice_adventure8() {

            ...

            //initial event listeners

            addEventListener(Event.ENTER_FRAME, CampScene);

}

public function CampScene(event:Event) {
           
            //remove the event listener
            removeEventListener(Event.ENTER_FRAME, CampScene);
                       
            //add the initial camp scene
            campScene.x = -120;
            campScene.y = -10;
            addChild(campScene);
            setChildIndex(campScene, 0);
           
            //add event listener to see if guy walking to campfire or not
            campScene.addEventListener(Event.ENTER_FRAME, walkUpToCampfire);
    
}

//IF WALKING BACK TO CAMPSCENE
        public function walkUpToCampfire(event:Event) {
           
            //if guy is walking back from ax
            if (comingFromAx == true) {

                //event listeners
                campScene.guyAtCampScene.gotoAndPlay("guyComingFromAx");
                campScene.addEventListener(Event.ENTER_FRAME, ifGuyDoneWalking);
           
            //else if initial creation
            } else {
               
                //remove old event listener
                //campScene.removeEventListener(Event.ENTER_FRAME, walkUpToCampfire);
               
                //trace("comingFromAx=FALSE");
                //event listeners
                campScene.addEventListener(Event.ENTER_FRAME, sceneHoverInfo);
                campScene.goToAx.addEventListener(MouseEvent.MOUSE_UP, goToAxScene);
                //campScene.goToBridge.addEventListener(MouseEvent.MOUSE_UP, goToBridgeScene);
            }
        }

//IF WALKING BACK TO CAMPSCENE DONE
        public function ifGuyDoneWalking(event:Event) {
           
            //if guy has finished walking
            if (campScene.guyAtCampScene.currentLabel == "guyAtCampSceneNormal") {
               
                //reset the scene booleans
                comingFromAx = false;
               
                //add the event listeners
                campScene.addEventListener(Event.ENTER_FRAME, sceneHoverInfo);
                campScene.goToAx.addEventListener(MouseEvent.MOUSE_UP, goToAxScene);

            }
        }

//GET READY FOR NEW SCENE

public function goToAxScene(event:MouseEvent) {
                                       
                //remove any movement event listeners
                campScene.goToAx.removeEventListener(MouseEvent.MOUSE_UP, goToAxScene);


                //stop all relevant sounds
                SoundMixer.stopAll();
               
                //play clip of guy walking to AxScene
                campScene.guyAtCampScene.gotoAndPlay("guyGoingToAx");
               
                //check for label to see if axScene should appear
                campScene.guyAtCampScene.addEventListener(Event.ENTER_FRAME, addScene);
        }

TOPICS
ActionScript
1.1K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

LEGEND , Feb 18, 2014 Feb 18, 2014

YOur best bet to resolve why things happen is to make use of the trace function.  In this case you could have a trace execute anytime that listener gets addedand any time it gets removed.  That way you should be able to see whether it was added back in after you removed it.  If there are multiple places where it gets added, then adjust your traces to indicate which line is involved as well.

Translate
LEGEND ,
Feb 18, 2014 Feb 18, 2014

You have so many event listeners in the code you show that it is difficult for me to associate it with your explanation.  I cannot tell which listener is in question.  The listener has to still be present in order for it to function.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 18, 2014 Feb 18, 2014

Ned Murphy wrote:

You have so many event listeners in the code you show that it is difficult for me to associate it with your explanation.  I cannot tell which listener is in question.  The listener has to still be present in order for it to function.

EDIT: If this is still hard as hell to understand, don't worry about it. I understand that having so much code that one didn't write - especially written unprofessionally - can be hard to understand. Thanks anyways for attempting anyways.

Sorry, the event listener in question is "campScene.goToAx.addEventListener(MouseEvent.MOUSE_UP, goToAxScene);". It is used in two or three different places, but it is only suppose to run once depending on whether a condition is true or false.

I remove it in the function goToAxScene(event:MouseEvent), the bottom-most function.  I do have that same event listener in question listening elsewhere (in the function ifGuyDoneWalking), but it's only set to listen if a condition is true, and my code is not set to run the condition as true (the }else{ is what runs in walkUpToCampfire). Nevertheless, that event listener seems to still be listening, even though the removal "campScene.goToAx.removeEventListener(MouseEvent.MOUSE_UP, goToAxScene);" runs in the bottom-most function.

I'm wondering if this is because "campScene.addEventListener(Event.ENTER_FRAME, walkUpToCampfire);", the event listener in the second function from the top, was not removed and thus it was still listening for a MouseEvent, or something to that extent. If I remove that event listener under the "}else{" in "walkUpToCampfire"("campScene.removeEventListener(Event.ENTER_FRAME, walkUpToCampfire);"), I appear to have no problems.

public function CampScene(event:Event) {
    
           ...

            campScene.addEventListener(Event.ENTER_FRAME, walkUpToCampfire);
    
}

public function walkUpToCampfire(event:Event) {

            if (condition == true) {


                campScene.guyAtCampScene.gotoAndPlay("guyComingFromAx");
                campScene.addEventListener(Event.ENTER_FRAME, ifGuyDoneWalking)

            } else {
               
                //if I have the line of code below running, the click is only listened for once, which is what I want.

               //I'm trying to understand why I have to remove this event listener if the listener I want to turn off

               //"campScene.goToAx.addEventListener(MouseEvent.MOUSE_UP, goToAxScene);", is turned off

               //in function "goToAxScene".
                //campScene.removeEventListener(Event.ENTER_FRAME, walkUpToCampfire);

                campScene.addEventListener(Event.ENTER_FRAME, sceneHoverInfo);
                campScene.goToAx.addEventListener(MouseEvent.MOUSE_UP, goToAxScene);
                //campScene.goToBridge.addEventListener(MouseEvent.MOUSE_UP, goToBridgeScene);
            }
        }

// only suppose to run if (condition == true), which it isn't
public function ifGuyDoneWalking(event:Event) {

            if (campScene.guyAtCampScene.currentLabel == "guyAtCampSceneNormal") {
              
                condition = false;
          
                campScene.goToAx.addEventListener(MouseEvent.MOUSE_UP, goToAxScene);

            }
        }


public function goToAxScene(event:MouseEvent) {
                                       
                //suppose to remove the movement event listener, but it seems to keep listening elsewhere
                campScene.goToAx.removeEventListener(MouseEvent.MOUSE_UP, goToAxScene);


        }

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 18, 2014 Feb 18, 2014

YOur best bet to resolve why things happen is to make use of the trace function.  In this case you could have a trace execute anytime that listener gets addedand any time it gets removed.  That way you should be able to see whether it was added back in after you removed it.  If there are multiple places where it gets added, then adjust your traces to indicate which line is involved as well.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 19, 2014 Feb 19, 2014

I had actually been using various trace statements, but for what it's worth, your comment about so many event listeners encouraged me to try to find "a better way" to write my code, having only a handful of event listeners, constantly listening when appropriate, and instead turning on and off the ability for the mouse to click on things.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Feb 21, 2014 Feb 21, 2014

My guess would be that you've got more than one campScene instance involved, so you may not be removing the listener from the instance where it was added. My recommendation would be to do one of two things:

  1. Listen to campScene for REMOVED_FROM_STAGE whenever you add any other listeners, then clean up those listeners in the handler.
  2. Use a Getter/setter pair for campScene, and clean up all outgoing instances when the value of campScene changes. That would look something like this:

public function get campScene():MovieClip {//also, please start specifying return types on your functions!

     return _campScene;

}

public function set campScene(value:MovieClip):void {

     if (value != _campScene) {

          if (_campScene) {

               _campScene.removeEventListener('someEvent', someHandler);

          }

          _campscene = value;

          if (_campScene) {

               //if you want to make sure you're listening to the new instance, add listeners here

          }

     }

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Feb 21, 2014 Feb 21, 2014

I solved this, but thanks. I'm sure your advice is useful but still a bit out of my league of understanding. (Like, I don't know why I want to return something.) Could you give me an example of how I could make use of REMOVED_FROM_STAGE with a listener and the follow-up function?

Amy Blankenship wrote:

My guess would be that you've got more than one campScene instance involved, so you may not be removing the listener from the instance where it was added. My recommendation would be to do one of two things:

  1. Listen to campScene for REMOVED_FROM_STAGE whenever you add any other listeners, then clean up those listeners in the handler.
  2. Use a Getter/setter pair for campScene, and clean up all outgoing instances when the value of campScene changes. That would look something like this:

public function get campScene():MovieClip {//also, please start specifying return types on your functions!

     return _campScene;

}

public function set campScene(value:MovieClip):void {

     if (value != _campScene) {

          if (_campScene) {

               _campScene.removeEventListener('someEvent', someHandler);

          }

          _campscene = value;

          if (_campScene) {

               //if you want to make sure you're listening to the new instance, add listeners here

          }

     }

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Mar 04, 2014 Mar 04, 2014
LATEST

If you're not returning something, you should specify a return type of void (the exception being the constructor, and in that case the lack of a return type then makes it easier to determine that what you're looking at is the constructor.

You'd use the REMOVED_FROM_STAGE listener something like this:

//note lack of return type. This is the constructor, but I don't know the name of your Class so I can't make it match

public function MainDocument() {

     super();

     //removed from stage doesn't bubble, need to listen on capture

     addEventListener(Event.REMOVED_FROM_STAGE, checkForCampSceneRemoval, true);

}

protected function checkForCampSceneRemoval(e:Event):void {

     //This will trigger whenever anything is removed, which is why the other solution

     //is preferable in most cases. Check to see if this is the thing we care about.

     var instance:MovieClip = e.target as MovieClip;

     if (instance.name=='campScene') {

          instance.removeEventListener('someEvent', someHandler);

     }

}

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines