构建小型GUI引擎:可见与addChild/removeChild

Gri*_*lij 5 flash user-interface actionscript-3

目前,我正在尝试一个非常简单的GUI绘图......"引擎"(我想你可以称之为).它的要点:

  1. 有一个FrontController受到用户请求的攻击; 每个请求都有一个uid
  2. 每个uid(读"页面")都有一个声明它存在的组件("模块")
  3. 组件是Sprite子类,实质上是唯一的

当然,我需要一种隐藏/显示这些精灵的方法.目前,我非常喜欢Flex默认情况下 - 就像"如果我们在comp可见的地方,创建它,缓存它并在每次再次可见时重复使用它".

现在的问题是-这将是隐藏和显示的更适当的和有效的方式-通过addChild/ removeChild或肘节visible.

我看到它的方式是:

  • visible 快速而肮脏(在第一次测试时)
  • visible不会像Event.ADDED或那样创造一系列冒泡事件Event.REMOVED
  • 隐形组件不会获得鼠标事件

因此removeChild,当我确定,屏幕上不再需要该组件时(例如,缓存太大,我会调用)

stackoverflow'ers/AS3疯狂的人会怎么想?

更新:这是一个很好的阅读(忘了谷歌).

我会坚持visible; 它似乎更适合我的任务; 手册页上的"性能优化的Flash平台"由Adobe.69让我更有信心.

这是我为那些感兴趣的人测试的东西的代码片段:

package 
{
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import flash.utils.getTimer;

/**
 * Simple benchmark to test alternatives for hiding and showing
 * DisplayObject.
 * 
 * Use:
 * <code>
 * new DisplayBM(stage);
 * </code>
 * 
 * Hit:
 * - "1" to addChild (note that hitting it 2 times is expensive; i think
 * this is because the player has to check whether or not the comp is
 * used elsewhere)
 * - "q" to removeChild (2 times in a row will throw an exception) 
 * - "2" to set visible to true
 * - "w" to set visible to false
 * 
 * @author Vasi Grigorash
 */    
public class DisplayBM{
    public function DisplayBM(stage:Stage){
        super();

        var insts:uint = 5000;
        var v:Vector.<Sprite> = new Vector.<Sprite>(insts);
        var i:Number = v.length, s:Sprite
        while (i--){
            s = new Sprite;
            s.graphics.beginFill(Math.random() * 0xFFFFFF);
            s.graphics.drawRect(
                Math.random() * stage.stageWidth, 
                Math.random() * stage.stageHeight,
                10, 
                10
            );
            s.graphics.endFill();
            v[i] = s;
        }

        var store:Object = {};
        store[Event.ADDED] = null;
        store[Event.REMOVED] = null;
        var count:Function = function(e:Event):void{
            store[e.type]++;
        }
        var keydown:Function = function (e:KeyboardEvent):void{
            var key:String
            //clear event counts from last run
            for (key in store){
                store[key] = 0;
            }

            stage.addEventListener(Event.ADDED, count);
            stage.addEventListener(Event.REMOVED, count);

            var s0:uint = getTimer(), op:String;
            var i:Number = v.length;
            if (e.keyCode === Keyboard.NUMBER_1){
                op = 'addChild';
                while (i--){
                    stage.addChild(v[i]);
                }
            }
            if (e.keyCode === Keyboard.Q){
                op = 'removeChild';
                while (i--){
                    stage.removeChild(v[i]);
                }
            }
            if (e.keyCode === Keyboard.NUMBER_2){
                op = 'visibile';
                while (i--){
                    v[i].visible = true;
                }
            }
            if (e.keyCode === Keyboard.W){
                op = 'invisibile';
                while (i--){
                    v[i].visible = false;
                }
            }
            if (op){
                //format events
                var events:Array = [];
                for (key in store){
                    events.push(key + ' : ' + store[key])
                }

                trace(op + ' took ' + (getTimer() - s0) + ' ' + events.join(','));
            }

            stage.removeEventListener(Event.ADDED, count);
            stage.removeEventListener(Event.REMOVED, count);
        }

        //autodispatch
        stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown);
    }
}
}
Run Code Online (Sandbox Code Playgroud)

Pix*_*ant 2

可见对我来说更有意义(因为删除孩子表明了最终结果),并且是我在自己的项目中显示/隐藏时倾向于使用的。

我还假设 addChild 的性能稍差,但我没有做过任何测试。

编辑:我刚刚看到这篇Adobe文章http://help.adobe.com/en_US/as3/mobile/WS5d37564e2b3bb78e5247b9e212ea639b4d7-8000.html,其中指定当使用GPU渲染模式时,仅设置visible = false可能会对性能产生影响,因为有是绘制重叠对象的成本(即使它们不可见)。相反,建议完全移除孩子:

尽可能避免过度绘制。过度绘制是将多个图形元素分层,使它们相互遮挡。使用软件渲染器,每个像素仅绘制一次。因此,对于软件渲染,无论有多少图形元素在该像素位置相互覆盖,应用程序都不会造成性能损失。相比之下,无论其他元素是否遮挡该区域,硬件渲染器都会为每个元素绘制每个像素。如果两个矩形相互重叠,则硬件渲染器将绘制重叠区域两次,而软件渲染器仅绘制该区域一次。

因此,在使用软件渲染器的桌面上,您通常不会注意到过度绘制对性能的影响。然而,许多重叠的形状会对使用 GPU 渲染的设备的性能产生不利影响。最佳实践是从显示列表中删除对象而不是隐藏它们。