ADDED_TO_STAGE 触发问题

ADDED_TO_STAGE firing issues

已解决 - 底部有示例处理程序的解决方案。

有没有办法阻止 ADDED_TO_STAGE 事件多次触发。

我注意到,通过加载加载我的主文件的外部预加载器,任何后续 Movieclips 添加到舞台或嵌套多次,具体取决于深度。

预加载器 主要 - (添加到舞台)UINav 在 UINav class(添加任何按钮或 MovieClip)

如果我从 Main 测试 MovieClip, 结果 Main 触发一次,UINav 触发一次,但 UINav 内或超出 UINav 的任何 objects 触发两次,或三次,具体取决于它们的深度。

如果我从预加载器测试 MovieClip, 结果 Main 触发一次,UINav 触发一次,但 UINav 内或以外的任何 objects 触发三到四次,具体取决于它们的深度。

预加载器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

主要 Class :

包 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

站点 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

preLoader 的跟踪结果:

Main 的跟踪结果:

如您所见,预加载器为 UINav 触发两次,为 Header 触发三次,主要是为 UINav 触发一次,为 header 触发两次。

请提供任何线索,因为这是驾驶精神!?

我理解为什么会这样的本质,但是如果我在另一个 object 中添加一个 object,为什么它会考虑是否在每个级别的舞台上。如果我添加一个切换到最高 object 添加,在它被删除后,当它 re-adds 和 object 到舞台时它只触发一次!?

首先,这正常吗?我已经看到关于 ADDED_TO_STAGE 触发两次的类似示例提出的问题并尝试了所有但没有任何区别,我已经在初始化后清除并删除了所有 eventListeners 但没有任何区别。

有没有办法阻止这种情况发生,或者有人可以阐明使用嵌套 Movieclips 的最佳程序!?另外,如果这是正常的,这肯定也是使用外部预加载器的主要缺点吗?

提前致谢。

已解决:(感谢@ices_2)

对于任何其他受苦的人,这里是修改后的代码,使用 ADDED_TO_STAGE 和跟踪处理程序来查看添加和删除的事件。

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_FROM_STAGE事件:

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

再次感谢,网上有这么多人遭受痛苦的例子 ADDED_TO_STAGE 重复实例,但没有关于如何正确使用它们的真正解释。

每天都是上学日!

您没有清除事件侦听器,因为它们绑定到此,而不是舞台。 您应该像这样从 class 中删除事件侦听器:

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

此代码将仅在控制台中跟踪 "added" 一次。