我有一个可视组件,应该在更新后不是立即重新绘制,而是在屏幕刷新之前重绘。我成功使用了Event.RENDER
。
我遇到一个问题,如果我的组件是从另一个组件的渲染处理程序中更新的,则Flash会忽略必要的stage.invalidate()
命令。
这是有趣的代码。 主要课程:
public class StageInvalidateTest extends Sprite {
private var _c : Component;
public function StageInvalidateTest() {
stage.frameRate = 1;
setTimeout(start, 1000);
}
private function start() : void {
trace ("START", getTimer());
_c = new Component("C");
addChild(_c);
var c2 : Component = new Component("C2");
addChild(c2);
c2.update();
addEventListener(Event.RENDER, renderMain);
stage.invalidate();
}
private function renderMain(event : Event) : void {
trace ("RENDER main", getTimer());
removeEventListener(Event.RENDER, renderMain);
_c.update();
}
}
组件:
public class Component extends Sprite {
private var _name : String;
public function Component(name : String) {
_name = name;
}
public function update() : void {
trace ("UPDATE component", _name, getTimer());
addEventListener(Event.RENDER, renderComponent);
stage.invalidate();
}
private function renderComponent(event : Event) : void {
trace ("RENDER component", _name, getTimer());
removeEventListener(Event.RENDER, renderComponent);
}
}
以下是有趣的输出:
START 1994
UPDATE component C2 1995
RENDER component C2 1996
RENDER main 1996
UPDATE component C 1997
永远不会呈现组件C
。
问题:
以任何方式启用我的组件使用渲染事件的安全方法是什么?
我有两个简单的想法:
1)使用额外的计时器,调用stage.invalidate()
,延迟为0
(零)。计时器在第一次调用其事件处理程序时停止。渲染发生在更新后。 组件:
public class Component2 extends Sprite {
private var _name : String;
private var _timer : Timer;
public function Component2(name : String) {
_name = name;
_timer = new Timer(0);
_timer.addEventListener(TimerEvent.TIMER, handleTimer);
}
public function update() : void {
trace ("UPDATE component", _name, getTimer());
addEventListener(Event.RENDER, renderComponent);
_timer.start();
stage.invalidate();
}
private function handleTimer(event : TimerEvent) : void {
trace ("--- --- TIMER", _name, _timer.currentCount, getTimer());
_timer.stop();
event.updateAfterEvent();
stage.invalidate();
}
private function renderComponent(event : Event) : void {
trace ("RENDER component", _name, getTimer());
_timer.stop();
removeEventListener(Event.RENDER, renderComponent);
}
}
输出:
START 2005
UPDATE component C2 2006
RENDER component C2 2007
RENDER main 2007
UPDATE component C 2008
--- --- TIMER C 1 2021
RENDER component C 2022
似乎很漂亮,我想要的。嵌套渲染及时。但我从未见过人们使用这种方法。相反,他们坚持进入框架。使用像这样的计时器有考虑或副作用吗?定时器事件处理程序是否能够在任何情况下触发stage.invalidate
或是否存在预期的副作用?
2)使用ENTER_FRAME事件而不是计时器。缺点:帧速率可能较低,渲染可能会延迟。
组件:
public class Component3 extends Sprite {
private var _name : String;
public function Component3(name : String) {
_name = name;
}
public function update() : void {
trace ("UPDATE component", _name, getTimer());
addEventListener(Event.RENDER, renderComponent);
addEventListener(Event.ENTER_FRAME, enterFrame);
stage.invalidate();
}
private function enterFrame(event : Event) : void {
trace ("--- --- ENTER_FRAME", _name, getTimer());
renderComponent(event);
}
private function renderComponent(event : Event) : void {
trace ("RENDER component", _name, getTimer());
removeEventListener(Event.RENDER, renderComponent);
removeEventListener(Event.ENTER_FRAME, enterFrame);
}
}
输出:
START 1994
UPDATE component C2 1995
RENDER component C2 1996
RENDER main 1996
UPDATE component C 1997
--- --- ENTER_FRAME C 2994
RENDER component C 2994
清楚地表明,C
的渲染时间为1 sek。
再次提问:
以任何方式启用我的组件使用渲染事件的安全方法是什么?
答案 0 :(得分:1)
没什么安全的,Adobe仍然没有注意这个bug。这就是为什么除了RENDER事件之外,每个人都使用ENTER_FRAME多年。为什么要问?)你不是AS3Commons-UI的创建者吗?
最近发了你的skype授权顺便说一句,你在吗?