[英]addChild() - DisplayObject isn't visible immediately
当我将DisplayObject添加到 function 中的DisplayObjectContainer (例如Sprite到Sprite )时,似乎实际上不是立即添加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
。
一些事件 - 不是全部,但最重要的事件包括MouseEvent
、 TimerEvent
和KeyboardEvent
- 有一个updateAfterEvent
方法,这将强制 flash 播放器在事件处理后立即呈现。
请注意,此选项应谨慎处理。 如果您的帧率下降到现在,您会看到处理鼠标事件和渲染更改之间的延迟,那么在播放器上强制进行更多渲染可能不是最好的主意。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.