0

我花了将近 1 周的时间来学习使用对象而不是数组。我认为调用它们并创建一些对象并设置它们的属性很容易。但是我现在无法访问它们,我尝试了这个:

function onBoxClick(event:MouseEvent):void {
    var str:String = event.currentTarget.name;
    trace(str);
    str = str.substring(str.indexOf("_") + 1);
    trace(getChildByName("copy_" + str)); // trying to trace an object by name
}

我的问题是是否有处理对象的实用方法,否则使用它们的目的是什么。

编辑:这是我用来创建影片剪辑和其他东西的函数:

function addBoxes(isUpdate:Boolean):void {
    var copyOne:Object = getReadOnlyValues();
    copyOne.name = "copy_" + num;

    // Set default mc1 settings
    var settings1:Object = copyOne.mc1Settings;
    for(var num2:String in settings1) {
        copyOne.mc1[num2] = settings1[num2];
    }

    // Set default mc1text settings
    var settings2:Object = copyOne.mc1TextSettings;
    for(var num3:String in settings2) {
        copyOne.mc1Text[num3] = settings2[num3];
    }

    copyOne.mc1.x = nextXpos;
    copyOne.mc1.name = "captionBox_" + num;

    addChild(copyOne.mc1);
    copyOne.mc1.addEventListener(MouseEvent.CLICK, onCaptionClick);

    copyOne.mc1Text.name = "captionBoxText_" + num;
    copyOne.mc1.addChild(copyOne.mc1Text);

    // ---------------------------------------------------------------  
    // Set default mc2 settings
    var settings4:Object = copyOne.mc2Settings;
    for(var num4:String in settings4) {
        copyOne.mc2[num4] = settings4[num4];
    }

    // Set default mc2text settings
    var settings5:Object = copyOne.mc2TextSettings;
    for(var num5:String in settings5) {
        copyOne.mc2Text[num5] = settings5[num5];
    }

    copyOne.mc2.x = nextXpos;
    copyOne.mc2.y = copyOne.mc1.height;
    copyOne.mc2.name = "box2_" + num;

    addChild(copyOne.mc2);

    copyOne.mc2Text.name = "box2BoxText_" + num;
    copyOne.mc2.addChild(copyOne.mc2Text);

    copyOne.mc2.addEventListener(MouseEvent.CLICK, onBoxClick);

    if (num / subunits is int) {
        trace (num);

        // createMc("normalBox", true);
    }

    nextXpos = nextXpos + copyOne.mc2.width;

    // traceObj(copyOne);
    // traceObj(getReadOnlyValues());
}

我在一个循环中调用了这个函数,所以我创建了许多电影剪辑。现在我无法访问对象的属性及其子项(例如文本字段)。

我在舞台上拥有的对象:Movieclips 和 textfields

它们来自哪里:上面的函数

我想用它们做什么:跟踪movieclips 和 textfields(由对象持有)以更改它们的子项(textfield)文本

会发生什么而不是我的期望:跟踪代码输出未定义而不是给我对象类型trace(getChildByName("copy_" + str)); // trying to trace an object by name

是否有一种实用的方法可以访问名称为“copy_1”的对象及其名称为“box2_1”(movieclip)的属性?

4

3 回答 3

1

One problem I see is the "copyOne" object has been created within the scope of "addBoxes", so it will no longer exist outside of this function.

Another is you're trying to access an Object via getChildByName, which only addresses displayObjects of the displayObjectContainer you are calling from.

If you want to loosely keep track of variables with things like Objects or MovieClips (which are both dynamic-style objects that let you add properties to them as you wish), just use MovieClips to house your values. The movieClips, being on the stage, will be retained in memory until removed from the displayList (stage).

Also, check out the Dictionary, a sort of key/value based way of storing collections of objects.

Better yet, if you use strongly-typed custom objects (creating your own classes to extend MCs, and adding your own public or private methods and values), there are benefits such as using Vectors (fancy, fast arrays that are compatible with any Object type you choose).

于 2015-01-21T18:21:14.307 回答
0

Array 和 Object 都是数据结构。数据意味着某种形式的信息。数据结构意味着某种形式的信息以某种方式存储。

数组和对象是存储信息的两种不同方式。

数组用整数标识数据。用于标识数组单个元素的整数称为索引

数组非常适合表示属于彼此的相似事物的列表。

var names:Array = ["John", "Paul", "George", "Ringo"];

这通常意味着数组的元素是相同类型的,就像上面的例子一样。但他们不必:

var numbers:Array = [42, "twenty-five", "XIIV"];

对于上面的例子,很容易回答“四个披头士乐队的名字是什么?”,“您在穿越这座历史悠久的小镇时偶然发现了哪些不同的数字表示形式?”。其他问题更难或不可能回答。“你在历史名城偶然发现了哪些罗马数字?”

对象用名称标识数据。标识对象的单个元素的名称称为属性

对象非常适合表示属于彼此的不同事物的列表。

var paula:Object = {age:37, name:"Paula", hairColor:0x123456};

这通常意味着对象的元素是不同类型的,就像上面的例子一样。但他们不必:

var car:Object = {manufacturer:"Porsche", color:"red", sound:"wroooooom", soundOfDriver:"weeeeeeeeeeee"};

考虑到这一点,让我们看一下您的代码,看看它是如何应用的。大局是你有一个addBoxes你多次调用的函数。由于一个函数应该有一个目的,这个函数每次执行时都会做类似的事情。哦:“类似”。无论这个函数的结果是什么,它都应该进入一个数组。对该函数的每次调用都将是数组的一个元素。您可以在使用“num”来识别当前函数运行中发生的任何事情时清楚地看到这一点。

您的函数中存在哪些数据?

  • 复制一
  • mc1
  • mc1Text
  • mc2
  • mc2Text

copyOne 在这里是个麻烦制造者,是什么导致了您的困惑。它试图一次完成所有事情,因此您无法清楚地考虑何时使用数组以及何时使用对象。人们会称它为神物。这不是一个很好的对象。

您对变量名的选择非常糟糕。您选择像“mcX”这样的超级通用名称只是为了稍后添加一个名称属性来描述它的真正含义。但即便如此,对于“Box2”应该是什么来说,这也不成立。 选择名称以便于理解代码中的内容。 看起来您为这个问题创建了这个结构的全部或部分,因此缺少有意义的名称。 我强烈建议你不要通过这些编造的项目来学习。但来自现实世界。

因此,我将强加以下目标: mc1 和 mc1Text 代表标题 mc2 和 mc2Text 代表内容

有了这一切,我再次问:

您的函数中存在哪些数据?

  • 标题框
  • 标题文字
  • 内容框
  • 内容文本

标题和内容都由一个框和一个文本组成。这些是不同的东西,因此标题和内容都是具有“框”和“文本”属性的对象。人们可能会认为,由于这种相似性,它们都应该放入一个数组中。但我不敢苟同。标题和文本不是一回事。你处理字幕和文本的方式不同。走在街上,你可能很快就会在新闻中看到一个大标题,但不是很长的文字。这就是为什么它们中的每一个都应该是在函数中创建的对象的属性。

这是一个结论

var allBoxes:Array = [];  // array to store the similar results of every function call

function createBoxes():void 
{
    var boxes:Object = {};

    //the box consists of caption & content, both bying of the same type, but are containing different data

    boxes.caption = {box:{}, text:{}}; //caption
    boxes.content = {box:{}, text:{}}; //content

    allBoxes.push(boxes);
}

就是这个。这就是我使用对象和数组对数据建模的方式和原因。

但这并没有结束。我的结论缺少您发布的很多代码。虽然以上内容大部分与语言无关,但缺少的代码特定于 Actionscript,而不仅仅是关于如何对数据建模。如下...

As3 是面向对象的。这很好,因为上面的结论里面有很多对象。要定义某个对象是/做/移动/放屁/等等,需要创建类。

发生以下更改(出于此答案范围之外的原因):

  • createBoxes(以前称为 addBoxes)调用扩展 Sprite 的类“CaptionAndContent”的构造函数。
  • 不再需要显式地创建一个对象“盒子”,因为构造函数正是这样做的。
  • captionandcontent不会有属性“box”,因为它们可以是 box 本身。这正是问题代码中的做法。默认设置在其类的构造函数中设置。

这是简化的代码片段,希望能说明类的外观。每个类都应该在自己的文件中,具有必要的导入、包块和您在问题中未指定的附加功能。

public class CaptionAndContent extends Sprite
{
    private var caption:Caption;
    private var content:Content;

    public function CaptionAndContent(captionText:String = "", contentText:String = "")
    {
        caption = new Caption(captionText);
        addChild(caption);

        content = new Content(contentText);
        content.y = caption.height;
        addChild(content);
    }
}

public class ClickableBoxWithText extends Sprite
{
    protected var textField:TextField;
    public function ClickableBoxWithText(text:String = "")
    {
        textField = new TextField();
        textField.text = text;
        addChild(textField);

        addEventListener(MouseEvent.CLICK, onClick);
    }

    protected function onClick(mouseEvent:MouseEvent):void
    {
        //override this in a sublclass
    }
}

public class Caption extends ClickableBoxWithText
{
    public function Caption(text:String = "")
    {
        super(text);

        // apply all the default settings of caption here.
    }
}

public class Content extends ClickableBoxWithText
{
    public function Content(text:String = "")
    {
        super(text);

        // apply all the default settings of content here.
    }
}

使用它们看起来像这样:

var allBoxes:Array = [];  // array to store the similar results of every function call

function createBoxes():void
{
    var captionAndContent:CaptionAndContent = new CaptionAndContent("This is the caption...", "...for this content");
    captionAndContent.x = nextXpos;
    addChild(captionAndContent);

    allBoxes.push(captionAndContent);
}

最后但并非最不重要的一点是点击处理程序中的识别问题。您的问题已经包含答案:

event.currentTarget

那是对被点击的对象的引用。在我的代码中

mouseEvent.currentTarget

这已经标识了对象。查找其属性之一(例如其名称)以在所有对象中搜索该名称是没有意义的,只是为了识别您已经必须识别(没有名称)以获得名称的同一对象。

无论如何,您都没有通过名称来识别对象。名称之间的区别以及据说使它们独一无二的是它们末尾的数字。正如在这个答案中所指出的,这就是所谓的索引,你试图用它来识别的东西应该进入一个数组。在我的示例代码中,这是allBoxes.

于 2015-01-21T21:32:27.183 回答
0

我真的不知道我是否理解你的问题,但正如@ozmachine 在他的回答中所说,你不能使用getChildByName,相反我认为你可以看看这个,可能会有所帮助:

var container:DisplayObjectContainer = this;

function getReadOnlyValues():Object {
    return {
        mc1: new box(),
        mc1: {
            name: 'mc1_',
            alpha: 1,
            x: 0,
            y: 0,
            width: 30,
            height: 25
        },
        mc1Text: new TextField(),
        mc1Text: {
            text: 'test',
            x: 0,
            y: 0,
            selectable: false,
            multiline: false,
            wordWrap: false
        }
    }
};

// create 5 objects
for(var i=0; i<5; i++){

    container['copy_'+i] = getReadOnlyValues();

    var obj:Object = getObjectByName('copy_'+i);
        obj.mc1.alpha = 1;
        obj.mc1.x = 0;
        obj.mc1.y = 50 * i;
        obj.mc1.width = 100;   

        obj.mc1.addChild(obj.mc1Text);
        obj.mc1Text.text = 'test_' + i;

    addChild(obj.mc1);
}
// get object by name
function getObjectByName(name:String):Object {
    return container[name];
}

// change the text of the 4th button
stage.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void { 
    var obj:Object = getObjectByName('copy_3');
        obj.mc1Text.text = 'new text';
})
于 2015-01-21T18:49:49.240 回答