开发者

How to safely trigger stage.invalidate()?

I have a visual component that should redraw after updates not immediately but right before the screen refresh. I use the Event.RENDER successfully.

I encountered a problem that if my component is updated from within a render handler of another component, the necessary stage.invalidate() command is ignored by Flash.

Here is the interesting code. Main class:

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();
    }
}

The component:

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);
    }
}

Here is the interesting output:

START 1994
UPDATE component C2 1995
RENDER component C2 1996
RENDER main 1996
UPDATE component C 1997

Component C is never rendered.

The question:

What is a safe way to anyhow enable my component to use the render event?


I have two quick ideas:

1) Use an additional timer which calls stage.invalidate() with a delay of 0 (zero). The timer stops with the first invocation of its event handler. The rendering occurs right after the update. The Component:

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);
    }
}

Output:

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

Seems to be pretty that what I wanted. Nested renderings just in time. But I never did see people use this approach. Instead, they stick to enter frame. Are there considerations or side effects using the timer like this? Is the timer event handler able to trigger stage.invalidate in any case or are there expected side effects?

2) Use an ENTER_FRAME event instead of the timer. Disadvantage: Frame rate might be low, and the rendering might be delayed.

The Component:

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);
    }
}

The Output:

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

Shows clearly, that the rendering of C comes 1 sek later.


Question again:

What is a safe way to anyhow enable my component to use the render event?


Nothing safe, Adobe still don't give attention to this bug. That's why everyone uses ENTER_FRAME in addition to RENDER events for years. Why asking?) Aren't you creator of AS3Commons-UI?

sent u skype authorization recently btw, are you there?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜