【发布时间】:2012-04-19 16:54:04
【问题描述】:
目前,我正在试验一个非常简单的 GUI 绘图……“引擎”(我猜你可以这么称呼它)。要点:
- 有一个 FrontController 被用户请求击中;每个请求都有一个uid
- 每个 uid(读作“页面”)都有其上存在的组件(“模块”)的声明
- 组件是 Sprite 子类,本质上是独一无二的
当然,我需要一种隐藏/显示这些精灵的方法。目前,我拥有它就像 Flex 默认拥有它一样 - 方式是“如果我们在一个 comp 可见的地方,创建它、缓存它并在每次它再次可见时重用它”。
问题是 - 通过addChild/removeChild 或切换visible,哪种方式更合适、更有效地隐藏和显示。
我的看法是这样的:
-
visible又快又脏(在第一次测试中) -
visible不会创建像Event.ADDED或Event.REMOVED这样的冒泡事件链 - 不可见的组件不会获得鼠标事件
所以removeChild 将是我确定时调用的东西,该组件将不再需要在屏幕上(或者缓存太大,例如)
stackoverflow'ers / AS3-crazy 的人是怎么想的?
更新: 这是good read(忘了谷歌)。
我会坚持visible;它似乎更适合我的任务; Adobe 的手册“优化 FLASH 平台的性能”,第 15 页。 69给了我更多的信心。
这是我为感兴趣的人测试的代码 sn-p:
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);
}
}
}
【问题讨论】:
-
如果我需要隐藏/显示的内容会占用大量资源,通常我会在设置其可见性时删除Child/addChild。如果它是较小的或不太复杂的图形或文本字段,我将设置它的可见性或 alpha。这完全取决于您需要隐藏/显示什么
-
@Ronnie removeChild 仅从显示列表中删除项目 - 仅此而已。
-
对不起,我也将它设置为 null 并在需要时重新创建
-
我之前从未真正考虑过 removeChild 与可见的区别,但我想到了一件事。如果它仍然在舞台上 IE visible=false 那么它可能仍然在获取 events/enterFrame 不确定它并且没有经过测试。可能值得创建一个测试来查看 enterframe 是否仍然被触发(我认为不会)并查看是否触发了任何阶段事件。
-
@Ronnie 如果有需要大量资源的东西 - 不要触摸它的显示列表并重新创建它是有意义的 O-)。目前,我发现创建可视化组件是所有操作中最繁重的操作(尽管组合仍然非常简单)。 @The_asMan
visible不影响stage。因为,stage仍然存在,我假设所有与舞台相关的听众都会被解雇。这就是为什么除了设置visible之外,我还在考虑一个(取消)激活特定组件的功能。
标签: actionscript-3 flash user-interface