У меня есть визуальный компонент, который должен перерисовываться после обновлений не сразу, а прямо перед обновлением экрана.Я успешно использую Event.RENDER
.
Я столкнулся с проблемой, что если мой компонент обновляется из обработчика рендеринга другого компонента, необходимая команда stage.invalidate()
игнорируется Flash.
Вот интересный код. Основной класс :
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 сек позже.
Снова вопрос:
Какой безопасный способ как-нибудь разрешить моему компоненту использоватьрендер события?