当我在一个函数中将 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>
答案 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
。
某些事件 - 并非所有事件,但最重要的事件包括MouseEvent
,MouseEvent
和TimerEvent
- 都有KeyboardEvent
方法,强制闪光处理事件后立即渲染的播放器。
请注意,应谨慎处理此选项。如果您的帧速率下降到目前为止,您会看到正在处理的鼠标事件与正在渲染的更改之间的延迟,强制在播放器上进行更多渲染可能不是最佳选择。