addChild() - DisplayObject 不立即可见

发布于 2024-11-29 22:25:57 字数 1592 浏览 1 评论 0原文

当我在函数中将 DisplayObject 添加到 DisplayObjectContainer (例如 SpriteSprite)时,似乎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() 函数,直到某个堆栈完全执行或其他什么才执行?

When I add a DisplayObject to a DisplayObjectContainer (e.g. a Sprite to a Sprite) in a function, it seems that the DisplayObject is actually added not immediately, but after finishing the function.

See this example:

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

So we have a simple green button, and when it is clicked, there's a red Sprite constructed and added to the stage.
But actually the red Sprite isn't visible until the onClick() function has been fully executed.

Why is that and what can I do for the red Sprite to be visible immediately?

Is there some (for the developer invisible) global paint() or update() function, that is not executed until some stack is fully executed or something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

微凉 2024-12-06 22:25:57

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

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

您的屏幕已绘制或重绘直到所有帧代码执行完毕。

Is there some (for the developer invisible) global paint() or update()
function, that is not executed until some stack is fully executed or
something?

Yes there is something. Here a random link (via google): http://blog.johannest.com/2009/05/22/the-movieclip-life-cycle-event-frame_constructed-and-event-exit_frame/

Your screen is drawn or redrawn not until all frame code is executed.

伤痕我心 2024-12-06 22:25:57

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

This is more related to the single threaded nature of Flash than anything else. The way it works is that it executes any code that is in response to an interaction event (your code). Then, any code that is in response to a prerender event (not used that much) and once all that is done, finally renders.

This flow of events has been likened to an elastic racetrack.

Should your code take a very long time to run, this will delay the subsequent rendering.

So, if you want to display a progress indicator or similar you will at the very least need to wait with your processing to the next time around the "track", preferably split over multiple frames to keep your UI nice and responsive. The simplest version of this would be to use a timer to delay the calculations ever so slightly.

 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();
}
你怎么这么可爱啊 2024-12-06 22:25:57

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

  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,所以屏幕不会留空。

The previous answer is relevant regarding frame construction, be also advised that several useful events are available to help you deal with the display list slugginess on objects adding/removing:

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

Here an Event.ADDED_TO_STAGE is listened, prior to launching the time-consuming routine, so the screen is not left empty.

雨落□心尘 2024-12-06 22:25:57

原因如下:

Flash 播放器按帧渲染显示列表。它分派 Event.ENTER_FRAME,准备渲染(在 MovieClip 等中移动播放头),然后分派 Event.RENDER(假设您使舞台无效),然后渲染,然后在离开后调度 Event.EXIT_FRAME

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

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

某些事件 - 不是全部,但最重要的事件,包括 MouseEventTimerEventKeyboardEvent - 具有 updateAfterEvent 方法,这将在处理事件后立即强制 Flash 播放器渲染

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

The reason is the following:

The flash player renders the display list frame-wise. It dispatches Event.ENTER_FRAME, to prepare for rendering (move around play heads in MovieClips etc.), then Event.RENDER (supposing you invalidated the stage), then renders and then dispatches Event.EXIT_FRAME after having left.

Therefore, any subsequent changes to the display list will not be visible before the next frame is rendered - unless forced.

However, between exit frame and the next enter frame, all events from I/O and timers are being dispatched. The mouse is also in input device, thus MouseEvents are processed at this moment.

Some events - not all, but the most important ones including MouseEvent, TimerEvent and KeyboardEvent - have an updateAfterEvent method, that will force the flash player to render immediately after the event is processed.

Please note, that this option should be handled with care. If your framerate drops so far, that you see the delay between the mouse event being processed and the changes being rendered, forcing more rendering on the player might not be the best idea.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文