2011-08-17 38 views
2

當我添加的DisplayObject的DisplayObjectContainer(如雪碧雪碧)的功能,似乎的DisplayObject實際上是不是立即添加,而是在完成功能後。的addChild() - 的DisplayObject是不是立即可見

見這個例子:

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

因此,我們有一個簡單的綠色按鈕,單擊時,有構建一個紅色雪碧並添加到舞臺上。 但實際上,直到onClick()函數已完全執行後,纔會看到紅色的Sprite

爲什麼是這樣,我能做些什麼紅色的雪碧立即可見?

是有一些(針對開發商不可見的)全球paint()方法更新()功能,即不執行,直到一些棧完全執行什麼的?

+0

什麼是fps設置? – 2011-08-17 17:56:04

+0

試試這個.invalidateDisplayList() – 2011-08-17 18:00:12

+0

Sprite不是mx.core.UIComponent,所以這個函數在那裏不存在。 – Morrandir 2011-08-18 13:44:06

回答

1

這比Flash的單線程本質更重要。它的工作方式是它執行任何響應交互事件(代碼)的代碼。然後,任何響應prerender事件的代碼(不會那麼用),一旦完成,最終呈現。

此事件流程has been likened to an elastic racetrack

如果您的代碼需要很長時間才能運行,則會延遲隨後的渲染。

所以,如果你想顯示一個進度指示器或類似的,你至少需要等待你的處理到下一次圍繞「軌道」,最好是分割多個幀,以保持你的UI很好, 。最簡單的版本是使用計時器來延遲計算。

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

以前的答案是關於相關的框架結構,也告知一些有用的事件可以幫助你處理的對象添加/刪除顯示列表slugginess:

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

這裏的Event.ADDED_TO_STAGE是在啓動耗時的例程之前,需要偵聽,因此屏幕不會留空。

1

其原因如下:

Flash播放器呈現的顯示列表逐幀。它會調度Event.ENTER_FRAME,爲渲染作準備(在影片剪輯中移動播放頭等),然後Event.RENDER(假設您已使舞臺無效),然後呈現,然後在離開後調度Event.EXIT_FRAME

因此,任何後續變化到顯示列表將不可見之前的下一幀被渲染 - 除非被迫

但是,在退出幀和下一個輸入幀之間,所有來自I/O和定時器的事件都將被調度。鼠標也在輸入設備中,因此此時處理MouseEvent

一些事件 - 不是全部,但最重要的,包括MouseEventTimerEventKeyboardEvent - 有一個updateAfterEvent方法,這將迫使flash播放器渲染在處理事件之後。

請注意,這個選項應該小心處理。如果您的幀率下降到目前爲止,您看到正在處理的鼠標事件與正在渲染的更改之間的延遲,則強制播放器上的更多渲染可能不是最好的主意。