如何在AS3中使用变量编写带有迭代的对象名?

时间:2016-04-16 04:51:01

标签: actionscript-3

假设我想创建几个(或更多)按钮,其实例名称如“button_1”等。通过迭代数字组件,是否有办法循环遍历函数或事件处理程序中的所有实例实例名称?

例如:

for (i = 1; i < 5; i++) {
    btn_[i].addEventListener(MouseEvent.CLICK, onBtn_[i]Click);
}

为了消除:

//btn_2.addEventListener(MouseEvent.CLICK, onBtn_2Click);
//btn_3.addEventListener(MouseEvent.CLICK, onBtn_3Click);
//btn_4.addEventListener(MouseEvent.CLICK, onBtn_4Click);
//btn_5.addEventListener(MouseEvent.CLICK, onBtn_5Click);  

感谢您提供的任何帮助。

我认为通过让事件监听器引用回事件的目标,有更好的方法吗?但是我现在对此并不太担心,只是想知道如何专门迭代对象实例。

哦,我发布的代码抛出了这个:

1084: Syntax error: expecting rightparen before Click.

谢谢,全部!

2 个答案:

答案 0 :(得分:3)

你想要什么

  

我想制作几个(或更多)按钮,其实例名称如&#34; button_1&#34;

不,你真的不想这样做,它是

  • 乏味:如果你需要50个按钮怎么办?你真的想手工命名吗?
  • 容易出错:如果你在某处弄错了怎么办?或者你在复制和放弃时搞砸了一些东西粘贴名称的共同部分?如果您忘记号码或使用两次会怎么样?
  • 不易维护:如果要删除按钮3到7怎么办?你如何处理数字差距?如果你想在中间包含2个按钮怎么办?您是否重命名以下所有按钮?
  

实例名称的数字组件?

名称非常适合识别特定的单个对象,但如果列表应该是详尽无遗的,那么列出单个名称并不是理想的解决方案。

如果你的兄弟是 Jack,Sam和Robin 你会在演讲中用那个名单来引用他们吗?或者你只是说我的兄弟

你需要什么

  

没有办法循环遍历所有实例

这是实际需要的东西。你有几个对象,你需要一些机制来分组它们。

有几种这样的机制可以结合使用:

Array

数组只是一个列表。所有按钮的列表是您要查找的分组机制。使用数组中的所有按钮和函数可以迭代数组:

var buttons:Array = [btn_1, btn_2];
var functions:Array = [onBtn_1Click, onBtn_2Click];

这将允许您做一些与您要求的非常相似的事情:

for (var i:int = 1; i < buttons.length; i++) {
    buttons[i].addEventListener(MouseEvent.CLICK, functions[i]);
}

这仍有一些问题:

  • 必须明确命名按钮和函数
  • 手动填充数组实际上增加了另一层复杂性,这似乎是多余的,并且本身容易出错:如果添加按钮但忘记将其添加到数组中该怎么办?

我们必须进一步了解。

不是对Array

的改进

等待!有[]括号的这个很酷的技巧,允许你组装名称和东西。

嗯,确实有可能使用所述括号动态访问对象的属性。

如果您有一个具有属性的对象:

var object:Object = {property:"hello world"};

您有两种可能性来访问此属性。点语法:

trace(object.property);

和括号:

trace(object["property"]);

使用括号,可以动态选择属性名称:

var object:Object = {property:"hello world"};
var propertyName:String = "property";
trace(object[propertyName]);

因此可以以任何方式组装:

var object:Object = {property:"hello world"};
var propertyName:String = "prop";
propertyName += "erty";
trace(object[propertyName]);

由于实例名称已转换为时间线的属性名称,因此您可以通过以下方式访问实例:

this["button_" + 1]

现在您可以轻松填充数组,例如按下其中一个按钮:

var buttons:Array = []; //creating an empty array

for (var i:int = 1; i < 5; i++) {
    buttons.push(this["button_" + i]);
}

问题在于它并没有解决实际问题。它只是让一项荒谬的任务变得乏味乏味。

您仍然需要为按钮键入所有这些个人名称。没有什么能阻止您输入错误的名称,名称两次或跳过值。

你会发现这个&#34;解决方案&#34;整个互联网,但它更像是一个快速和肮脏的黑客,只是看起来很聪明,但并没有真正帮助解决潜在的问题。

DisplayObjectContainer

显示所有按钮。这意味着他们在显示列表中。您可以使用代码访问和操作该列表。

这听起来很可疑,之前有Array这个事情也是一个清单,它并没有真正解决问题。

不同之处在于按钮自动显示在显示列表中。你不必做任何事情。 您无需使用名称识别它们。

显示列表由MovieClip等容器组成。 每个容器可以包含其他容器,而容器又可以包含容器等。

这是怎么回事:

  1. 在时间轴上创建一个空的MovieClip,并为其指定实例名称buttonContainer
  2. 将所有按钮添加到buttonContainer。按钮不需要具有实例名称!
  3. 它有点像数组,但你可以直观地组装它,你不需要单独的实例名称,只需要一个容器。

    容器也知道里面有多少东西。要迭代它们,你也可以使用for循环。这是一个使按钮半透明的例子:

    for (var i:int = 0; i < buttonContainer.numChildren; i++) {
            buttonContainer.getChildAt(i).alpha = 0.5;
    }
    

    此代码适用于该容器中的几乎任意数量的按钮。 您所要做的就是确保将按钮添加到容器中。

    好的,现在我该怎么做这些功能?

    这就是问题所在:你做不到。没有内置的机制可以将显示对象的功能组合在一起。

    事件系统

      

    我认为通过让事件监听器引用回事件的目标,有更好的方法吗?

    确实有解决每个按钮具有单独功能的问题。相反,只有一个函数可以与事件源一起使用:currentTarget。这就是这样一个函数看起来像半透明度的东西:

    function onClick(e:MouseEvent):void
    {
        currentTarget.alpha = 0.5;
    }
    

    您现在可以将此功能添加到所有按钮:

    for (var i:int = 0; i < buttonContainer.numChildren; i++) {
            buttonContainer.getChildAt(i).addEventListener(MouseEvent.CLICK, onClick);
    }
    

    那就是它!简单明了:将此侦听器添加到该容器中的所有按钮。没有名字巫术。只是一个容器。

    优越的解决方案

    老兄!你带着你的甜蜜时光与上面所有的胡言乱语,介绍一个接近另一个的解决方案,只有最后一个实际完成工作。现在这个俗气的副标题是什么问题?这个人怎么会不那么有效?

    以上所有假设列表中的所有按钮都是实际目标,实际上它解决了问题。但是如果你考虑一下,上面的所有内容都只是试图尽可能地聪明地将各个按钮放在列表中。 this["button_" + i]有其缺陷,DisplayObjectContainer解决方案修复了它们,但引入了自己的解决方案:如果由于某种原因无法将所有按钮添加到容器中,该怎么办?如果有些在一个容器中而有些在另一个容器中会怎么样?

    您可以组合这些方法并将多个容器中的按钮添加到单个数组中,如下所示:

    var buttons:Array = [];
    
    for (var i:int = 0; i < containerA.numChildren; i++) {
            buttons(containerA.getChildAt(i));
    }
    
    for (i = 0; i < containerB.numChildren; i++) {
            buttons(containerB.getChildAt(i));
    }
    

    数组是独立于显示列表的超级容器。 这仍然很糟糕。如果按钮四处散落并且无法按容器分组怎么办?

    你还记得杰克,萨姆和罗宾吗?以及如何更容易地将它们称为&#34;我的兄弟&#34;作为一种名单?

    如果你想引用世界上所有的兄弟怎么办? 这似乎是一个荒谬的任务,但实际上是短语&#34;所有兄弟&#34;就是这么做的。它并没有说明它们有多少或哪些地方,但可以肯定它们指的是它们。它通过创建一个明确的列表来完成,但它们适合兄弟的定义:男性兄弟。

    您也不需要所有按钮的明确列表。您只想通过定义按钮的内容来隐式引用所有按钮。

    一个类就是这样的定义。不是通过名称,容器或您想象的任何其他方式来识别作为按钮的对象,而是定义按钮是什么并从该定义派生对象。

    这是一个文件TransparentButton.as的样子:

    package
    {
        public class TransparentButton extends SimpleButton
        {
            public function TransparentButton()
            {
                addEventListener(MouseEvent.CLICK, onClick);
            }
    
            private function onClick(e:MouseEvent):void
            {
                this.alpha = 0.5;
            }
        }
    }
    

    基本上,这定义了当创建按钮时,它会向自己添加一个监听器。该功能将其透明度降低到0.5。

    如果您现在将该类与库中的按钮元件相关联,则会导致您拖动的按钮实例。按照该类定义进入时间线。

    免责声明:此类不一定按原样运行,具体取决于按钮的符号类型(如果它们实际上是MovieClip,则会失败)。也许它缺少一些进口。

答案 1 :(得分:1)

您可以通过下面的数组语法访问该属性。

Obj["foo"] = "baz";
trace(Obj.foo);     // baz

但是,以下代码会出现构建错误。

["btn_1"].addEventListener      // NG

您可以通过添加“this”来避免错误。

this["btn_1"].addEventListener  // OK

所以这就是修复示例代码的答案。

for (i = 1; i <= 5; i++) {  // Fixed "<" to "<=". Because it seems you want to create 1 to 5.
    this["btn_"+i.toString()].addEventListener(MouseEvent.CLICK, this["onBtn_"+i.toString()+"Click"]);
}

.toString()是不必要的。 当串联String和Number时,该数字自动转换为String类型。这段代码也有效。

this["btn_"+i].addEventListener(MouseEvent.CLICK, this["onBtn_"+i+"Click"]);

此外,如果onBtn_1ClickonBtn_2Click以及onBtn_3Click ...是相似或常用的方法,我建议您将它们集成到一个函数onBtnClick
像这样。

for (i = 1; i <= 5; i++) {
    this["btn_"+i].addEventListener(MouseEvent.CLICK, onBtnClick);
}

function onBtnClick(event: MouseEvent): void{

    // Some common process.
    Button(event.target).visible = false;

    // You can get the id by using event.target.name
    if (event.target.name == "btn_1"){

    }
    else if (event.target.name == "btn_2"){

    }
    else{

    }

    // Some common process.
    doSomething();
}