【问题标题】:addChild() - DisplayObject isn't visible immediatelyaddChild() - DisplayObject 不立即可见
【发布时间】:2011-08-17 12:34:43
【问题描述】:

当我在函数中将 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() 函数,在某些堆栈完全执行之前不会执行?

【问题讨论】:

  • 试试 this.invalidateDisplayList()
  • Sprite 不是 mx.core.UIComponent,所以那里不存在这个函数。
  • 哎呀没有注意到它是一个精灵

标签: flash actionscript-3 flex4


【解决方案1】:

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

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

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

【讨论】:

  • 感谢您的快速回复,但是......好吧,我来自 Java,对框架事物的概念了解不多。 :-) 我正在开发一个纯 AS3 应用程序。看来我需要更深入地了解 Flash 机制...
  • 如果您有阻塞代码,请尝试提高其性能。如果不可能,请尝试使用 Timer 对象进行异步处理。
【解决方案2】:

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

此事件流has been likened to an elastic racetrack

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

因此,如果您想显示进度指示器或类似内容,您至少需要等待下一次围绕“轨道”进行处理,最好将其拆分为多个帧,以保持 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();
}

【讨论】:

  • 选择这个作为接受的答案,因为发布的链接帮助我更好地理解了这个主题。
【解决方案3】:

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

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

【讨论】:

  • 我已经测试了你的代码,因为我想知道我是否误解了某些东西。在您的示例中,红色框也出现延迟。当调用addChild() 时,ADDED_TO_STAGE 的所有事件处理程序都会立即执行。触发所有监听器后进行渲染。
【解决方案4】:

原因如下:

Flash 播放器逐帧呈现显示列表。它发送Event.ENTER_FRAME,准备渲染(在MovieClips 中移动播放头等),然后发送Event.RENDER(假设您使舞台无效),然后渲染,然后在完成后发送Event.EXIT_FRAME离开了。

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 2018-12-30
    • 1970-01-01
    • 2019-08-30
    • 2019-08-19
    • 2012-12-22
    • 1970-01-01
    相关资源
    最近更新 更多