Как безопасно вызвать stage.invalidate ()? - PullRequest
0 голосов
/ 13 сентября 2011

У меня есть визуальный компонент, который должен перерисовываться после обновлений не сразу, а прямо перед обновлением экрана.Я успешно использую 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 сек позже.


Снова вопрос:

Какой безопасный способ как-нибудь разрешить моему компоненту использоватьрендер события?

1 Ответ

1 голос
/ 14 сентября 2011

Ничто не безопасно, Adobe все еще не обращает внимания на эту ошибку. Вот почему каждый год использует ENTER_FRAME в дополнение к событиям RENDER. Почему вы спрашиваете?) Вы не создатель AS3Commons-UI?

недавно отправил вам авторизацию в Skype, кстати, вы там?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...