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

时间:2012-04-05 23:08:13

标签: actionscript-3 flash user-interface

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

  1. 有一个受用户请求影响的FrontController;每个请求都有 uid
  2. 每个 uid (读取“页面”)都有一个声明存在于其中的组件(“模块”)
  3. 组件是 Sprite 子类,实质上是唯一的
  4. 当然,我需要一种隐藏/显示这些精灵的方法。目前,我非常喜欢Flex默认使用它 - 就像“如果我们在comp可见的地方,创建它,缓存它并在每次再次可见时重复使用它”。

    问题是 - 通过addChild / removeChild或切换visible,这是更合适有效的隐藏和展示方式。

    我认为的方式是:

    • visible快速而肮脏(首次测试时)
    • visible不会创建一系列冒泡事件,例如Event.ADDEDEvent.REMOVED
    • 不可见的组件不会获得鼠标事件

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

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

    更新: 这是一个good read(忘了谷歌)。

    我会坚持visible;它似乎更适合我的任务; Adobe的手册“优化FLASH平台的性能”,第2页。 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);
        }
    }
    }
    

3 个答案:

答案 0 :(得分:2)

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

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

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

  

尽可能避免透支。透支是多层次的   图形元素使它们相互模糊。使用该软件   渲染器,每个像素只绘制一次。因此,对于软件   渲染,应用程序不会产生任何性能损失   在该像素处有多少图形元素相互覆盖   地点。相比之下,硬件渲染器为每个像素绘制每个像素   元素是否其他元素模糊了该区域。如果两个   矩形相互重叠,硬件渲染器绘制   当软件渲染器绘制区域时,重叠区域两次   只有一次。

     

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

答案 1 :(得分:1)

删除子项最好减少实例,事件并从闪存电影中释放内存。您可能会发现精灵可能会相互影响。从它们的绘制方式或列表中,垃圾收集通常也会发挥作用。实施此方法可以最终适应您的应用程序

可见仍然在内存中有精灵,它当前没有被绘制。你也可以保存精灵然后删除它,然后在需要时重新加载它将是一个理想的所有解决方案。 使用数组来存储数据是另一种解决方案,还取决于你的应用程序是如何实现的,很难说,因为我们不知道,lol

添加子项性能我会说压力较小,因为它仍然只有项目添加与隐藏的倍数。在这些隐藏的子项“s”中,属性与侦听器一起存储在内存中。

答案 2 :(得分:0)

以下是Moock关于这个主题的一些硬数据: http://www.developria.com/2008/11/visible-false-versus-removechi.html

                  Children on the                     Single-frame 
                  Display List    .visible   .alpha   Elapsed Time (ms)
No Children       0               --         --       4
Non-visible       1000            false      1        4
Zero Alpha        1000            true       0        85
Fully Visible     1000            true       1        1498
90% Transparent   1000            true       .1       1997