Flash Builder 4 -> コントロール配列

Posted by muchag | ActionScript 3.0,Flash Builder 4 |
初回投稿:2010-07-11 (日) 1:33:42 | 最終更新:2010-07-25 (日) 2:26:08

コントロール配列 なんていうタイトルにしてみたけど
これは VB 用語なんだそうな。

ActionScript 界では何ていうのかな?

要するに、同種のコンポーネントを未定数個配置して一括制御したい わけだ。

  1. Textbox0_txt.text = myArray[0];
  2. Textbox1_txt.text = myArray[1];
  3. Textbox2_txt.text = myArray[2];
  4.  ・
  5.  ・
  6.  ・
  7. Textbox30_txt.text = myArray[30];

こんな風にコードを書いているんじゃ大変だし
変更があったらメンドイからねぇ。。。

しかも毎回数が変わるわけだから、予め書きようがない。
 

手法1:コンポーネントの ID で配列化

Flash は今まで MX, 8, CS3 と使ってきたが、ずっと ActionScript 2.0。
このときは、インスタンス名に番号を付けることで実現してきた。
[as2]for (var i:Number = 0; i < 31; i++ ) { eval("_root.Textbox" + i +"_txt").text = myArray(i); }[/as2] ってことは、今回も各コンポーネントに付ける ID で実現できそう。 インスタンスの参照 -> 変数の利用

と思ったら甘かった。

  1. // ステート上に myGroup を設置済み
  2. var myArray:Array = new Array("Flash", "Dreamweaver", "Illustrator");
  3. for (var i:int = 0; i < 3; i++) {
  4.     var myLabel:Label = new Label();
  5.     myLabel.id = "myLbl" + i;
  6.     myLabel.text = myArray[i];
  7.     myGroup.addElement(myLabel);
  8.  
  9.     Alert.show(myGroup["myLbl" + i].text);
  10. }[/as3]
  11.  
  12. としても
  13.  
  14. [as3]// ステート上に myGroup を設置済み
  15. var myArray:Array = new Array("Flash", "Dreamweaver", "Illustrator");
  16. for (var i:int = 0; i < 3; i++) {
  17.     var myLabel:Label = new Label();
  18.     myLabel.id = "myLbl" + i;
  19.     myLabel.text = myArray[i];
  20.     myGroup.addElement(myLabel);
  21. }
  22.  
  23. Alert.show(myGroup["myLbl0"].text);
  24. [/as3]
  25.  
  26. としても、実行時エラーになる。
  27. <div class="fb4error">ReferenceError: Error #1069: spark.components.Group にプロパティ myLbl0 が見つからず、デフォルト値もありません。</div>
  28.  
  29. Flex User Group:<a href="http://www.fxug.net/modules/xhnewbb/viewtopic.php?topic_id=1096" target="_blank">コントロールの取得方法</a>
  30. こちらにも同様の実行時エラーが載っている。
  31.  
  32. しかし、回答者の方々は、この手法でいける と書いているので
  33. 私がどこか間違えているらしい。
  34.  
  35. ん~。。。   :-|
  36.  
  37. <div class="flow2">this</div>
  38. <a href="http://diaspar.jp/node/164" target="_blank">Drag&Drop で参考にさせていただいたサイト</a>で <span class="emphasis_b">this</span> を用いて参照しているのを見た。
  39. [as3]this['opt'+i]

こちらのプロジェクトを実際に動かしてみる。
おー 参照できてるやん!

早速私のプロジェクトに引用・・・あれ? 動かない・・・。

イベントで受け取った target の id を参照することはできても、
id を用いてコントロール自体を参照することができない。

グーグル先生・・・。
FXUF:addChildでid設定

どうやら MXML で設定した idAS で設定した id は、微妙に異なるらしく
AS で設定した id へは参照できないっぽい。 意味ね~!!!

大体、上記フォーラム内容にある id が重複してもOK なんて・・・ありえにゃい・・・orz
 

ClassFactory

また、上記フォーラム内容にある ClassFactory を用いる方法も試してみたが
親コンポーネントへ登録する際にエラーになる。

1061: 未定義である可能性のあるメソッド addChild を、静的型 mx.core:ClassFactory の参照を使用して呼び出しました。 Flex の問題
1061: 未定義である可能性のあるメソッド addElement を、静的型 mx.core:ClassFactory の参照を使用して呼び出しました。 Flex の問題

Adobe® Flex® 4.1 リファレンスガイド:ClassFactory
を見てみたものの、よくわからない・・・放置。 😐
 

途中経過

そういうわけで、現在までのところでは
MXML で設定した id なら、ths[id] で参照可能
AS で設定した id の場合は、参照不能
 

手法2:コンポーネントへの参照を配列へ格納

で、結局 ActionScript 界で何ていうのかわからない「コントロール配列」。
わからないので、グーグル先生にも上手く質問ができなかった。
 

お手本発見

それでも、あれこれ試して探していると
2ch:Flexでもswf作ろうぜ
の313番にいいものを見つけた。

<以下、引用>
コントロール配列が欲しいなら自分で用意すればいい

var textarray:Array = new Array();
for (var i:int = 0; i <= 3; i++) { var text:TextField = new TextField(); text.text = String(i); text.x = i*10 text.y = i*10 addChild(text); textarray[i] = text; } removeChild(textarray[1]);[/as] 例えばArrayでやるならこんな感じで <以上、引用> ほうほう、これを見る限りでは、コンポーネント(オブジェクト)への参照を配列に格納できるのか。 よって、配列に格納される値は、以下のような感じになる。 [text]test.ApplicationSkin2._ApplicationSkin_Group1.contentGroup.TextField** // **は数字が入る[/text]   id を設定している場合はこんな感じ。(text.id = "myTF" だとして) [text]test.ApplicationSkin2._ApplicationSkin_Group1.contentGroup.myTF[/text]  

自分用に改変

これが書かれたのが 2008/07/11(金) 00:32:33 なので
上記コードを FB4 用にちょいちょい手を入れて

  1. // ステート上に myGroup を設置済み
  2. var myArray:Array = new Array("Flash", "Dreamweaver", "Illustrator");
  3. var myCompornentArray:Array = new Array();
  4. for (var i:int = 0; i < 3; i++) {
  5.     var myLabel:Label = new Label();
  6.     myLabel.text = myArray[i];
  7.     myGroup.addElement(myLabel);
  8.     myCompornentArray[i] = myLabel;
  9. }
  10. myGroup.removeChild(textarray[1]);[/as3]
  11. としてみたら、希望通り動いた。
  12.  
  13. <div class="flow2">Array と ArrayCollection</div>
  14. 因みに、これを ArrayCollection でやると実行時エラーになる。
  15. 上下のコードの3行目に注目。
  16. [as3]// ステート上に myGroup を設置済み
  17. var myArray:Array = new Array("Flash", "Dreamweaver", "Illustrator");
  18. var myCompornentArray:ArrayCollection = new ArrayCollection(); // 注目
  19. for (var i:int = 0; i < 3; i++) {
  20.     var myLabel:Label = new Label();
  21.     myLabel.text = myArray[i];
  22.     myGroup.addElement(myLabel);
  23.     myCompornentArray[i] = myLabel;
  24. }
  25. myGroup.removeChild(textarray[1]);[/as3]
  26. <div class="fb4error">RangeError: 指定したインデックス '0' が範囲外です
  27.     at mx.collections::ListCollectionView/setItemAt()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\collections\ListCollectionView.as:531]</div>
  28.  
  29. 経験者の方々にとっては当たり前なのかもしれないが
  30. <span class="emphasis_b">Array</span> と <span class="emphasis_b">ArrayCollection</span> との区別がしっかりついていない現時点では貴重な資料。
  31.  
  32. <div class="file">FB4 インストールディレクトリ\sdks\4.0.0\frameworks\projects\framework\src\mx\collections\ListCollectionView.as:531</div>
  33. を見ると
  34. [as3 num=525]public function setItemAt(item:Object, index:int):Object
  35. {
  36.     if (index < 0 || !list || index >= length)
  37.      {
  38.         var message:String = resourceManager.getString(
  39.             "collections", "outOfBounds", [ index ]);
  40.         throw new RangeError(message);
  41.     }
  42.  
  43.     var listIndex:int = index;
  44.     if (localIndex)
  45.     {
  46.         if (index > localIndex.length)
  47.         {
  48.             listIndex = list.length;
  49.         }
  50.         else
  51.         {
  52.             var oldItem:Object = localIndex[index];
  53.             listIndex = list.getItemIndex(oldItem);
  54.         }
  55.     }
  56.     return list.setItemAt(item, listIndex);
  57. }

531行目はただのエラー処理なだけで
要は527行目に引っ掛かってる。

ArrayCollection だと、この時点で length が 0 になっているのでエラー。
この先は、気力と時間があるときに・・・。 🙄
 

お手本2

SilverFox2nd~狐の小屋~:コントロールを配列で参照
ここにもお手本があった。

上とほぼ同じだが、配列そのものをインスタンスに設定しているパターン。

<以下、引用>
// Canvas型の配列変数を宣言
[ArrayElementType(“mx.containers.Canvas”)] public var CvsAry:Array = new Array();
 ・
 ・ 中略
 ・
private function InitFunc():void {
 ・
 ・ 中略
 ・
for ( i = 0; i < RightCnt; i++ ) {  ・  ・ 中略  ・ // Canvasのインスタンス作成 CvsAry[i] = new Canvas(); CvsAry[i].width = CvsW; CvsAry[i].height = CvsH; CvsAry[i].setStyle("backgroundColor", "0x000000");  ・  ・ 中略  ・ }  ・  ・ 中略  ・ }[/as3] <以上、引用> こちらも希望通り動いた。 更に [as3 num=2][ArrayElementType("mx.containers.Canvas")][/as3] こういうメタデータタグがあるということも学習できた。 Flex 3 コンポーネントの作成と拡張 / カスタムコンポーネントの開発 / カスタムコンポーネントのメタデータタグ :メタデータタグ

試しにこれを除いてみてもちゃんと動いたが
型宣言は大事だからね~。メモメモ。

Posted by muchag | ActionScript 3.0,Flash Builder 4 |
初回投稿:2010-07-11 (日) 1:33:42 | 最終更新:2010-07-25 (日) 2:26:08

コメントはまだありません »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment