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());
}

この関数をループで呼び出したので、多くのムービークリップを作成しました。オブジェクトのプロパティとその子 (テキスト フィールドなど) にアクセスできなくなりました。

ステージ上にあるオブジェクト: ムービークリップとテキストフィールド

どこから来たか: 上記の関数

それらを使ってやろうとしていること: ムービークリップとテキストフィールド (オブジェクトによって保持されている) をトレースして、それらの子 (テキストフィールド)

のテキストを変更する私が期待するもの: トレース コードtrace(getChildByName("copy_" + str)); // trying to trace an object by name

は、オブジェクト タイプを提供する代わりに未定義の出力を出力します。

4

3 に答える 3

1

問題の 1 つは、「copyOne」オブジェクトが「addBoxes」のスコープ内で作成されたため、この関数の外には存在しなくなることです。

もう 1 つは、呼び出し元の displayObjectContainer の displayObjects のみをアドレス指定する getChildByName を介してオブジェクトにアクセスしようとしていることです。

Objects や MovieClips (どちらも必要に応じてプロパティを追加できる動的なスタイルのオブジェクト) などで変数を大まかに追跡したい場合は、MovieClips を使用して値を格納します。ステージ上にあるムービークリップは、displayList (ステージ) から削除されるまでメモリに保持されます。

また、オブジェクトのコレクションを格納する一種のキー/値ベースの方法であるディクショナリも確認してください。

さらに良いことに、厳密に型指定されたカスタム オブジェクトを使用する場合 (独自のクラスを作成して MC を拡張し、独自の public または private メソッドと値を追加する)、Vectors (任意のオブジェクトと互換性のあるファンシーで高速な配列) を使用するなどの利点があります。選択したタイプ)。

于 2015-01-21T18:21:14.307 に答える
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 に答える
0

Array と Object はどちらもデータ構造です。データとは、何らかの形式の情報を意味します。データ構造とは、何らかの形式の情報が特定の方法で格納されていることを意味します。

配列とオブジェクトは、情報を格納する 2 つの異なる方法です。

配列は整数でデータを識別します。配列の 1 つの要素を識別するための整数をインデックスと呼びます

配列は、互いに属している類似のもののリストを表すのに理想的です。

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

これは多くの場合、上記の例のように、配列の要素が同じ型であることを意味します。しかし、彼らはする必要はありません:

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

上記の例では、「4 人のビートルズの名前は?」、「歴史的な町を旅しているときに、数字のどのような表現に出くわしましたか?」という質問に簡単に答えることができます。他の質問は答えるのが難しいか不可能です。「歴史ある街で出会ったローマ数字は?」

オブジェクトは名前でデータを識別します。オブジェクトの単一の要素を識別するための名前をプロパティと呼びます

オブジェクトは、互いに属している異なるもののリストを表すのに理想的です。

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

これは、多くの場合、上記の例のように、オブジェクトの要素が異なる型であることを意味します。しかし、彼らはする必要はありません:

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

これを考慮して、コードを見て、それがどのように適用されるかを見てみましょう。全体像は、addBoxes複数回呼び出す関数があるということです。1 つの関数には 1 つの目的があるため、この関数は実行されるたびに同様のことを行います。うーん、「似てる」。この関数の結果がどうであれ、配列に入れる必要があります。その関数への各呼び出しは、配列の要素になります。これは、関数の現在の実行で何が起こっているかを識別するために「num」を使用すると明確にわかります。

関数にはどのようなデータが存在しますか?

  • コピーワン
  • mc1
  • mc1Text
  • mc2
  • mc2Text

copyOne はトラブルメーカーであり、混乱の原因です。一度にすべてを実行しようとしているため、いつ配列を使用し、いつオブジェクトを使用するかについて明確に考えることができません。神のオブジェと呼べるでしょう。そして、それは周りに置くのに適したオブジェクトではありません.

変数名の選択は非常に悪いです。「mcX」のような非常に一般的な名前を選択するのは、それが実際に何であるかを説明する name プロパティを後で追加するためだけです。しかし、それでさえ、「Box2」が本来あるべきものには当てはまりません。 コード内の内容を簡単に理解できる名前を選択してください。 この構造のすべてまたは一部をこの質問用にjsutで作成したため、意味のある名前が不足しているようです。 このようなでっち上げのプロジェクトで学習しないことを強くお勧めします。でも現実世界から。

したがって、次の目標を課します: 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」のコンストラクターを呼び出します。
  • コンストラクターがまさにそれを行うので、オブジェクト「ボックス」を明示的に作成する必要はもうありません。
  • captionとはcontent、それ自体がボックスになる可能性があるため、プロパティ「ボックス」を持ちません。これはまさに質問のコードで行われている方法です。デフォルト設定は、それらのクラスのコンストラクターで設定されます。

これは、クラスがどのように見えるかをうまく説明するコードの抜粋です。各クラスは、必要なインポート、パッケージ ブロック、および質問で指定しなかった追加機能を含む独自のファイルに含める必要があります。

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

これにより、オブジェクトがすでに識別されます。名前を取得するために既に識別しなければならなかった同じオブジェクト (名前なし) を識別するためだけに、その名前のすべてのオブジェクトを検索するために、そのプロパティの 1 つ (たとえば、その名前) を検索することは無意味です。

とにかく、オブジェクトを名前で識別していません。名前の違いと、それらを一意にしていると思われるものは、末尾の数字です。この回答で指摘されているように、これはインデックスと呼ばれるものであり、識別しようとしているものは配列に入れる必要があります。私のコード例では、これはallBoxes.

于 2015-01-21T21:32:27.183 に答える