addChild() - DisplayObject不会立即可见

时间:2011-08-17 12:34:44

标签: flash actionscript-3 flex4

当我在一个函数中将 DisplayObject 添加到 DisplayObjectContainer (例如 Sprite Sprite )时,似乎 DisplayObject 实际上并没有立即添加,而是在完成功能之后。

见这个例子:

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()函数完全执行之前,红色的 Sprite 是不可见的。

为什么这样,我可以做些什么才能立即看到红色 Sprite

是否有一些(对于开发人员不可见)全局 paint() update()函数,在完全执行某些堆栈之后才会执行?< / p>

4 个答案:

答案 0 :(得分:2)

  

是否有一些(对于开发人员不可见)全局paint()或update()   函数,直到某个堆栈完全执行后才执行   什么?

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

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

答案 1 :(得分:1)

前面的答案与帧构造有关,还建议有几个有用的事件可以帮助你处理添加/删除对象的显示列表迟缓:

  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,因此屏幕不会为空。

答案 2 :(得分:1)

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

此事件流has been likened to an elastic racetrack

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

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

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

答案 3 :(得分:1)

原因如下:

Flash播放器以帧为单位呈现显示列表。它会调度Event.ENTER_FRAME,准备渲染(在MovieClip中移动游戏头等),然后Event.RENDER(假设你使舞台失效),然后渲染,然后调度{离开后{1}}。

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

但是,在退出帧和下一个输入帧之间,将分派来自I / O和定时器的所有事件。鼠标也在输入设备中,因此此时会处理Event.EXIT_FRAME

某些事件 - 并非所有事件,但最重要的事件包括MouseEventMouseEventTimerEvent - 都有KeyboardEvent方法,强制闪光处理事件后立即渲染的播放器。

请注意,应谨慎处理此选项。如果您的帧速率下降到目前为止,您会看到正在处理的鼠标事件与正在渲染的更改之间的延迟,强制在播放器上进行更多渲染可能不是最佳选择。