开发者

addChild() - DisplayObject isn't visible immediately

开发者 https://www.devze.com 2023-03-28 12:53 出处:网络
When I add a DisplayObject to a DisplayObjectContainer (e.g. a Sprite to a Sprite) in a function, it seems that the DisplayObject is actually added not immediately, but after finishing the function.开

When I add a DisplayObject to a DisplayObjectContainer (e.g. a Sprite to a Sprite) in a function, it seems that the DisplayObject is actually added not immediately, but after finishing the function.

开发者_开发百科

See this example:

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

So we have a simple green button, and when it is clicked, there's a red Sprite constructed and added to the stage. But actually the red Sprite isn't visible until the onClick() function has been fully executed.

Why is that and what can I do for the red Sprite to be visible immediately?

Is there some (for the developer invisible) global paint() or update() function, that is not executed until some stack is fully executed or something?


Is there some (for the developer invisible) global paint() or update() function, that is not executed until some stack is fully executed or something?

Yes there is something. Here a random link (via google): http://blog.johannest.com/2009/05/22/the-movieclip-life-cycle-event-frame_constructed-and-event-exit_frame/

Your screen is drawn or redrawn not until all frame code is executed.


This is more related to the single threaded nature of Flash than anything else. The way it works is that it executes any code that is in response to an interaction event (your code). Then, any code that is in response to a prerender event (not used that much) and once all that is done, finally renders.

This flow of events has been likened to an elastic racetrack.

Should your code take a very long time to run, this will delay the subsequent rendering.

So, if you want to display a progress indicator or similar you will at the very least need to wait with your processing to the next time around the "track", preferably split over multiple frames to keep your UI nice and responsive. The simplest version of this would be to use a timer to delay the calculations ever so slightly.

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


The previous answer is relevant regarding frame construction, be also advised that several useful events are available to help you deal with the display list slugginess on objects adding/removing:

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

Here an Event.ADDED_TO_STAGE is listened, prior to launching the time-consuming routine, so the screen is not left empty.


The reason is the following:

The flash player renders the display list frame-wise. It dispatches Event.ENTER_FRAME, to prepare for rendering (move around play heads in MovieClips etc.), then Event.RENDER (supposing you invalidated the stage), then renders and then dispatches Event.EXIT_FRAME after having left.

Therefore, any subsequent changes to the display list will not be visible before the next frame is rendered - unless forced.

However, between exit frame and the next enter frame, all events from I/O and timers are being dispatched. The mouse is also in input device, thus MouseEvents are processed at this moment.

Some events - not all, but the most important ones including MouseEvent, TimerEvent and KeyboardEvent - have an updateAfterEvent method, that will force the flash player to render immediately after the event is processed.

Please note, that this option should be handled with care. If your framerate drops so far, that you see the delay between the mouse event being processed and the changes being rendered, forcing more rendering on the player might not be the best idea.

0

精彩评论

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

关注公众号