esadude
esadude

Reputation: 47

ADDED_TO_STAGE firing issues

Resolved - Solution with example handlers at the bottom.

Is there a way to stop the ADDED_TO_STAGE event firing multiple times.

I've noticed that by loading an external preLoader which loads my Main file, any subsequent Movieclips added to the stage or nested fire multiple times depending upon the depth.

preLoader Main - (Add to stage) UINav In UINav class (add any button or MovieClip)

If I test the MovieClip from the Main, Result Main fires once, UINav fires once, but any objects within UINav or beyond fire twice, or three times depending upon their depth.

If I test the MovieClip from the preLoader, Result Main fires once, UINav fires once,but any objects within UINav or beyond fire three or four times depending upon their depth.

preloader Class :

package
{   

public class preLoader extends MovieClip
{

    public function preLoader()
    {
        if( stage ) added( null );
            else
            addEventListener( Event.ADDED_TO_STAGE, added );
    }
    private function added( event:Event ):void
    {
        stage.removeEventListener( Event.ADDED_TO_STAGE, added );
        stage.removeEventListener( Event.ADDED_TO_STAGE, init );
        trace( "preSite : "+ getQualifiedClassName( this ), "Initiated" );

        stage.scaleMode = StageScaleMode.NO_SCALE;
        stage.align = StageAlign.TOP_LEFT;
        stage.stageFocusRect = false;

        //loadStatusTxt on stage
        //preLoadText on stage

        var loader : Loader = new Loader();
        _targetLoaderInfo = loader.contentLoaderInfo;
        _targetLoaderInfo.addEventListener( ProgressEvent.PROGRESS, onProgress );
        _targetLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, errorIOHandler);
        _targetLoaderInfo.addEventListener( Event.COMPLETE , onLoaded );

        if( Capabilities.playerType != "External" )
        {
            loader.load( new URLRequest("Main.swf?id=" + myIdentifier) );
        } else {
            loader.load( new URLRequest("Main.swf") );
        }
    }

    private function errorIOHandler( event:IOErrorEvent ):void
    {
        trace( event.text );
    }

    private function onProgress( event:ProgressEvent ):void
    {

        var loaded : uint = event.bytesLoaded;
        var total : uint = event.bytesTotal;

        var percentLoaded:Number = Math.round( (loaded/total) * 100 );

        preLoadText.text = "Loading " + percentLoaded + "%";
        addChild( preLoadText );

        pLoader.x = stage.stageWidth / 2;
        pLoader.y = stage.stageHeight - 50;
        addChild( pLoader );

        _loadPercent = _targetLoaderInfo.bytesLoaded / _targetLoaderInfo.bytesTotal;
        updateLoader( _targetLoaderInfo.bytesLoaded /  _targetLoaderInfo.bytesTotal );

        if ( _loadPercent >= 100 )
        {
            onLoaded( event );
        }
    }

    private function updateLoader( num:Number ) : void {
        //num is a number between 0 and 1
        pLoader.mcPreloaderBar.width = num * 476;
    }

    private function onLoaded( e:Event ):void
    {
        _targetLoaderInfo.removeEventListener( ProgressEvent.PROGRESS, onProgress );
        _targetLoaderInfo.removeEventListener( IOErrorEvent.IO_ERROR, errorIOHandler );
        _targetLoaderInfo.removeEventListener( Event.COMPLETE , onLoaded );

        // TODO hide loader
        removeChild( pLoader );
        while ( this.numChildren > 0 )
        {
            this.removeChildAt( 0 );
        }           
        this.addChild( DisplayObject(LoaderInfo(e.target).content) );
        trace( "Class "+ getQualifiedClassName( this ), " - COMPLETE" );
    }

}//End Class
}// End Package

Main Class :

package com.misoLepto {

public class Main extends MovieClip
{

    public static var test_Main : Boolean = true;// true = Live / false = TraceEvents

    public var site_Background : Site_Background = new Site_Background();
    public var site_UINav : Site_UINav = new Site_UINav();

    public function Main()
    {
        if ( stage ) init();
        else    addEventListener( Event.ADDED_TO_STAGE, init );
    }
    public function init( event : Event = null):void
    {
        if( hasEventListener( Event.ADDED_TO_STAGE ))
        {
            stage.removeEventListener( Event.ADDED_TO_STAGE, init );
            trace( "YES Listener Main" );
        }
        else
        {
            trace( "NO Listener Main" );
        }
        GlobalVariable.stage = stage;

        //stage.removeEventListener(Event.ADDED_TO_STAGE, init);
        stage.addEventListener( Event.RESIZE, resizeMain );

        stage.scaleMode = StageScaleMode.NO_SCALE;
        stage.align = StageAlign.TOP_LEFT;

        setupMain();
    }
    private function toggleUINav( e:Event ):void {
        if( site_UINav.stage )
        {
            removeChild( site_UINav );
        }
        else
        {
            addChild( site_UINav );
        }
    }
    private function setupMain():void
    {
        addChild( site_UINav );
        stage.addEventListener( MouseEvent.CLICK, toggleUINav );
    }
    private function resizeMain( event : Event ) : void
    {
        trace("Resized Stage");
    }

}//End Class
}//End Package

UINav CLass :

package com.misoLepto {

public class Site_UINav extends MovieClip {

    public var site_Header : Site_Header = new Site_Header()

    public function Site_UINav()
    {
        if ( stage ) initUINav();
        else    addEventListener( Event.ADDED_TO_STAGE, initUINav, false, 0, true );
                addEventListener( Event.REMOVED_FROM_STAGE, removedUINav );
    }
    public function initUINav( event : Event = null ):void
    {

        stage.removeEventListener( Event.ADDED_TO_STAGE, initUINav );
        stage.addEventListener( Event.RESIZE, resizeUINav );
        setupUINav();
    }
    private function setupUINav():void {
        trace("UINav : Initiated");
        addChild( site_Header );
    }
    private function resizeUINav( event : Event ) : void
    {
        trace("Resized Stage");
    }
    private function removedUINav ( event : Event ):void
    {           
        stage.removeEventListener( Event.RESIZE, resizeUINav );
        stage.removeEventListener( Event.REMOVED_FROM_STAGE, removedUINav );
        removeChild( site_Header );
    }

}//End Class
}//End Package

Site Header Class :

package com.misoLepto {


public class Site_Header extends Sprite {

    public var headPanel : Sprite = new Sprite();
    public var lineColour : uint = new uint( 0x999999 );
    public var lineWidth : Number = new Number( 1 );
    public var headerColour : uint = new uint( 0xFFFFFF );

    public function Site_Header ()
    {
        if ( stage ) initHeader();
         else
         addEventListener( Event.ADDED_TO_STAGE, initHeader, false, 0, true );
         addEventListener( Event.REMOVED_FROM_STAGE, removedHeader );
    }
    public function initHeader ( e : Event = null ):void
    {
        stage.removeEventListener( Event.ADDED_TO_STAGE, initHeader );
        stage.addEventListener( Event.RESIZE, resizeHeader );

        headPanel.graphics.lineStyle( lineWidth, lineColour );
        headPanel.graphics.beginFill( headerColour, 1 );  
        headPanel.graphics.drawRoundRect( stage.stageWidth / 2, 2, stage.stageWidth / 2 - 3, 25, 10 );
        headPanel.graphics.endFill();
        trace( "HeaderPanel : Initialised" );
        addChild(headPanel);

        setupHeader();
    }
    public function resizeHeader( event : Event ) : void
    {
        if ( headPanel.stage )
        {
            headPanel.graphics.clear();
            headPanel.graphics.lineStyle( lineWidth, lineColour );
            headPanel.graphics.beginFill( headerColour, 1 );  
            headPanel.graphics.drawRoundRect( stage.stageWidth / 2, 2, stage.stageWidth / 2 - 3, 25, 10 );
            headPanel.graphics.endFill();
        }
        else
        {
            trace("headPanel not on screen");
        }
    public function removedHeader ( e : Event ):void {          
        stage.removeEventListener( Event.RESIZE, resizeHeader );
        stage.removeEventListener( Event.REMOVED_FROM_STAGE, removedHeader );
        headPanel.graphics.clear();
        removeChild( headPanel );
    }

}//End Class
}//End Package

Trace results from preLoader :

preLoader Results

Trace results from Main :

main Results

As you can see, the preloader fires twice for the UINav, and three times for the Header, and in the main it fires the UINav once and the header twice.

Any clues please as this is driving mental!?

I understand the essence of why this would be but if I'm adding an object within another object why does it account for if being placed on stage at each level. If I add a toggle to the highest object added, after its been removed, when it re-adds the object to the stage it only fires the once!?

Firstly, is this normal? I've seen issues raised about similar examples of ADDED_TO_STAGE firing twice and tried all but nothing makes a difference, I've cleared and removed all eventListeners after they are initialised but nothing makes a difference.

Is there a way to stop this from happenening or can someone please shed some light on the best procedure to work with nested Movieclips!? Also, if this is regular, surely this is a major drawback from using an external preloader too?

Thanks in advance.

Resolved : (thanks to @ices_2)

For any others suffering, here's the ammended code to use ADDED_TO_STAGE with trace handlers to see the event being added and removed.

public function Site_UINav()
{
        if ( this.stage ) initUINav();
        else
            this.addEventListener( Event.ADDED_TO_STAGE, initUINav );
            this.addEventListener( Event.REMOVED_FROM_STAGE, removedUINav );
    }
    public function initUINav( event : Event = null ):void
    {
        trace( "UINav listerner present (a): " + this.hasEventListener( Event.ADDED_TO_STAGE ));
        if(this.hasEventListener( Event.ADDED_TO_STAGE ))
        {
            //remove listener if it was added
            this.removeEventListener( Event.ADDED_TO_STAGE, initUINav );
        }
        trace( "UINav listerner present (b): " + this.hasEventListener( Event.ADDED_TO_STAGE ));
    }

Remove the REMOVE_FROM_STAGE event :

    private function removedUINav ( event : Event ):void
    {           
        stage.removeEventListener( Event.RESIZE, resizeUINav );
        trace( "UINav listerner present (c): " + this.hasEventListener( Event.REMOVED_FROM_STAGE ));
        if(hasEventListener( Event.REMOVED_FROM_STAGE ))
        {
            //remove listener if it was ever added
            this.removeEventListener( Event.REMOVED_FROM_STAGE, removedUINav );
        }
        trace( "UINav listerner present (d): " + this.hasEventListener( Event.REMOVED_FROM_STAGE ));
    }

Thanks again, so many examples online of people suffering ADDED_TO_STAGE duplicates instances and no real explanation as to how to use them correctly.

Everyday's a school day!

Upvotes: 1

Views: 238

Answers (1)

p.balmasov
p.balmasov

Reputation: 357

You are not clearing event listeners because they bind to this, and not the stage. You shold remove event listener from class like this:

public class Preloader extends MovieClip
{
    public function Preloader()
    {
        if (stage)
            this.init();
        else
            this.addEventListener(Event.ADDED_TO_STAGE, init);
    }

    private function added(event:Event):void
    {
        this.removeEventListener(Event.ADDED_TO_STAGE, init);
        trace("added");
    }
}

This code will trace "added" in console only one time.

Upvotes: 1

Related Questions