繁体   English   中英

addChild() - DisplayObject 不立即可见

[英]addChild() - DisplayObject isn't visible immediately

当我将DisplayObject添加到 function 中的DisplayObjectContainer (例如SpriteSprite )时,似乎实际上不是立即添加DisplayObject ,而是在完成 function 之后添加。

看这个例子:

package {
    import flash.display.Sprite;
    import flash.events.MouseEvent;

    public class AddChildTest extends Sprite {

        private var _sprite:Sprite;

        public function AddChildTest():void{            
            var button:Sprite = new Sprite();
            button.graphics.beginFill(0x00ff00);
            button.graphics.drawRect(0, 0, 50, 50);
            button.graphics.endFill();
            button.buttonMode = true;
            button.addEventListener(MouseEvent.CLICK, onClick);
            addChild(button);               
        }

        private function onClick(event:MouseEvent):void {
            _sprite = new Sprite();
            _sprite.graphics.beginFill(0xff0000);
            _sprite.graphics.drawRect(0, 0, 50, 50);
            _sprite.graphics.endFill();
            _sprite.x = 50;
            _sprite.y = 50;                     

            //this red sprite is not visible immediateley!
            addChild(_sprite);      

            //put something time-consuming here
            for (var i:int = 0; i < 2000; i++){
                trace(i);
            }
        }
    }
}

所以我们有一个简单的绿色按钮,当它被点击时,会有一个红色的Sprite被构建并添加到舞台上。 但实际上,在onClick() function 完全执行之前,红色Sprite是不可见的。

为什么会这样,我该怎么做才能让红色Sprite立即可见?

是否有一些(对于开发人员不可见的)全局paint()update() function,直到某个堆栈完全执行或其他内容才会执行?

是否有一些(对于开发人员不可见的)全局 paint() 或 update() function,直到某个堆栈完全执行或其他内容才会执行?

是的,有些东西。 这是一个随机链接(通过谷歌): http://blog.johannest.com/2009/05/22/the-movieclip-life-cycle-event-frame_constructed-and-event-exit_frame/

在执行所有帧代码之前,不会绘制或重绘屏幕。

上一个答案与框架构造有关,还请注意,有几个有用的事件可帮助您处理添加/删除对象时的显示列表迟滞问题:

  private function onClick(event:MouseEvent):void {
        _sprite = new Sprite();
        _sprite.graphics.beginFill(0xff0000);
        _sprite.graphics.drawRect(0, 0, 50, 50);
        _sprite.graphics.endFill();
        _sprite.x = 50;
        _sprite.y = 50;                     

        //this red sprite is not visible immediateley!
        _sprite.addEventListener(Event.ADDED_TO_STAGE, onReady);
        addChild(_sprite);      

    }

  private function onReady(e: Event): void {

        _sprite.removeEventListener(Event.ADDED_TO_STAGE, onReady);

        //put something time-consuming here
        for (var i:int = 0; i < 2000; i++){
            trace(i);
        }
    }

在启动耗时的例程之前,这里会监听 Event.ADDED_TO_STAGE,因此屏幕不会为空。

这与 Flash 的单线程性质有关。 它的工作方式是执行任何响应交互事件的代码(您的代码)。 然后,任何响应预渲染事件的代码(没有使用那么多),一旦完成,最终渲染。

这种事件流已被比作弹性跑道

如果您的代码需要很长时间才能运行,这将延迟后续渲染。

所以,如果你想显示一个进度指示器或类似的东西,你至少需要等待你的处理到下一次围绕“轨道”,最好分成多个帧,以保持你的 UI 漂亮和响应。 最简单的版本是使用计时器来稍微延迟计算。

 private function onClick(event:MouseEvent):void {
    // add sprite here

    var t:Timer = new Timer(50, 1);

    // i'm using an anonymous function here, however, a proper event handler 
    // function is probably cleaner

    t.addEventListener(TimerEvent.COMPLETE, function(e:Event):void {
        //put something time-consuming here
        for (var i:int = 0; i < 2000; i++){
            trace(i);
        }
    }
    t.start();
}

原因如下:

flash 播放器逐帧渲染显示列表 它分派Event.ENTER_FRAME以准备渲染(在影片剪辑中移动播放头等),然后分派Event.RENDER (假设您使舞台无效),然后渲染,然后在离开后分派Event.EXIT_FRAME

因此,在渲染下一帧之前,对显示列表的任何后续更改都将不可见 - 除非强制

但是,在退出帧和下一个进入帧之间,来自 I/O 和计时器的所有事件都被调度。 鼠标也在输入设备中,因此此时处理MouseEvent

一些事件 - 不是全部,但最重要的事件包括MouseEventTimerEventKeyboardEvent - 有一个updateAfterEvent方法,这将强制 flash 播放器在事件处理后立即呈现

请注意,此选项应谨慎处理。 如果您的帧率下降到现在,您会看到处理鼠标事件和渲染更改之间的延迟,那么在播放器上强制进行更多渲染可能不是最好的主意。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM