DataProviderとは何者か

勉強は集中してやらないと身に付かないね

 3年弱ほったらかしている間に「にゃあプロジェクト」さんがActionScript3.0の記事をしこたま書いてたよ、くっ先行者利益(?)を取れると思っていたのに、完全に負けてます。
 こうなったらびしばし参考にさせてもらいます。
 でも、標準のGUIコンポーネントについての記事は2011-02-12現在ないみたいなので、そこに関してはあんまり参考にならないですなー。
 標準のコンポーネントはAdobeのリファレンスをちゃんと読め、で終わりなのかなぁ世間様としては。

 さて、気を取り直して fl.data.DataProviderです。
 今回から、オブジェクト他にアイコン付けてみました。多少うるさい気もしなくはないですが、ちょっとでもビジュアルを入れて、地味な画面に潤いを。やたら付けてもうるさいので、付けるのはリファレンスへのリンクのみでいきます。

とりあえずDataProvider使ってみる

 えーDataProviderは、ListDataGridTileListComboBoxで使われているらしいです。
 前回に引き続きComboBoxで攻めてみましょう。てゆーか他のやつはまだ使い方分からないし。
 dataProviderプロパティの設定は、タイムラインでやらないと反映されなかったので、外部ASファイルは止めてスクリプトはタイムライン(フレームスクリプト)に書いていく。
 タイムラインに書くとflash系のパッケージの宣言がいらなくなるのと、publicとかprivateとかのスコープ指定が不要にというかできなくなります。
 タイムライン上のスクリプトの立ち位置が未だによくわからんちん。
 次のようにフレームスクリプトに書けばドロップダウンリストに反映される。

dropdownList.dataProvider = new DataProvider(  [ "labelA", "labelB" ] );

 あー、ConboBoxのインポートも必要ないのか。よくわかんないけど。
 イベントリスナもくっつけてみる。

dropdownList.dataProvider = new DataProvider(  [ "labelA", "labelB" ] );
dropdownList.addEventListener( Event.CHANGE, changeHandler );
function changeHandler( e:Event ):void {
	trace( "label:", e.target.selectedItem.label );
	trace( "data:", e.target.selectedItem.data );
}

 e.target.selectedItem.labele.target.selectedItem.dataともに、 "labelA"とか"labelB"が帰ってくる。
 ちなみにselectedItemはfl.data.SimpleCollectionItemじゃない。
 へほーん。よくわかんねーっす

 $ σ_σ$  < さっきから、一切分かってないみたいね。
 Σc ' _' )  < 俺もわかんねー
 $;σ_σ$  < あたしもだけど…ね

単体でDataProviderを使ってみる

 思うんだけど、DataProviderってコンポーネントに使わなくても、ArrayとかVector、Dictionar、XMLあたりのデータの一種として使えるんじゃなかろうか。
 そんなわけで DataProvider単体について調べてみよう、リファレンス読むぜー。

 Σc;' _' )  < 今まで、読んでなかったのかよ…

 とりあえず、Arrayとどう違うかという観点で読み進めてみよう。
 あ、Arrayも良く知らないんだよなー。

 $;σ_σ$  < よくもまぁそれでプログラム書いて、金貰ってるわね

 技術立国日本の現実を見た!!
 さて、社会派な話題はそのへんにして。リファレンスをざっくり読んでみました。

 DataProviderはflash.events.EventDispatcherを継承しているだけあって、イベントを発生させる。addEventListenerでリスナを登録できるワケ。
 これがどういう事を意味するかと言うと、同じDataProviderを登録しておけば、その登録したDataProviderを変更するだけで登録した全てのオブジェクトが更新される、という事だ。
 おおっ便利…というシーンがどれほどあるかは不明ですがー。

 しかしitemをそのままアイテムって訳してあるのが、凄く気になる。そこは項目じゃないかなぁ…。てゆーか他の箇所では項目と書いてあったりもするし、なにこの統一感のNASAアメリカ航空宇宙局。
 さて、var dp:DataProvider = new DataProvider( [ "labelA", "labelB" ] );とdpに入れた値を取り出すにはどうしたら良いか、 カンでdp[ 0 ]とやってみる…プロパティが存在しません、とまぁ当たり前の結果が返って来ました。
 真っ当にはdp.getItemAt( 0 )とやるみたい。で、dp.getItemAt( 0 ).labeldp.getItemAt( 0 ).dataとやってみると、何と値が帰ってくる。どうもDataProviderコンストラクタにArrayを渡した時のデフォルトのプロパティはlabelとdataらしい。…リファレンスのどこにも書いてないが。

 $;σ_σ$  < 結局リファレンス読まずに、とりあえず試してんのね

 リファレンスには「データソースとしてリスト、XML インスタンス、またはデータオブジェクトの配列を使用して、新しい DataProvider オブジェクトを作成します。」とか書いてあるけど、Array渡るやん、トラヴェルヤン!
 では、真っ当なリファレンスに書いてある方法でコンストラクトしてみましょうか。

var dp:DataProvider = new DataProvider(  [ { label:"labelA" }, { label:"labelB" } ] );

 ふむ、dp.getItemAt( 0 ).labelは"labelA"、dp.getItemAt( 0 ).dataはundefindeだ。dataが設定されなかったら、自動的にlabelから持ってくるって訳じゃないようだ。
 なお、ここのオブジェクト ({}で括っているところ)のプロパティは、何を使っても構わないようだ。ただし、標準のコンポーネントのデフォルト設定ではlabelとdataを使うので、その作法にそって作っておいた方が無難そうだ。

XMLをDataProviderに突っ込んでみる

 DataProviderのシンコッチョーは、XMLデータをコンストラクタに渡せる事だ。
 では、渡してみよう。…カンで!

var dp:DataProvider = new DataProvider( <items><label>labelA</label><label>labelB</label></items> );

 ふーむ、dpと各項目までは作られているけど、その項目のプロパティは作られてない。

var dp:DataProvider = new DataProvider( <items><item label= "labelA"/><item label= "labelB"/></items> );

 こうかな?

 $ σ_σ$  <「かな?」って、どんだけリファレンスマニュアル読みたくないのよ、この人

 お、行けた行けた!
 じゃ、これはどうだ?

 $;σ_σ$  < もうね…なにも言う事ないわ
var dp:DataProvider = new DataProvider( <items><item><label>labelA</label></item><item><label>labelB</label></item></items> );

 ヤフー、行けるぜっ。こりゃ凄い。ActionScript3.0って凄くない?てゆーかDataProviderコンポーネントか。このパース能力は侮れないな。
 こうなると、ちょっと意地悪してみたくなるな。

var dp:DataProvider = new DataProvider( <items><item label="labelA"><label>labelA'</label></item><item label= "labelB"><label>labelB'</label></item></items> );

 "labelA'"の方が表示された。属性より要素優先なのね。
 階層を深くしてみたり。

var dp:DataProvider = new DataProvider( <items><a><item label="labelA"><label>labelA'</label></item><item label= "labelB"><label>labelB'</label></item></a></items> );

 これは取れない(取らない?)か、流石に。
 それから、items、itemのタグ名は何でも構わないようだ。おお便利!おおっ!

 ただまぁ…このへんのことActionScript2.0のコンポーネントだとデータバインドでオーサリングツール上でできたんだよな、確か。

addItemで追加

 コンストラクタで生成する方法は、だいたい分かった。
 次は、空のDataProviderを作っておいて、addItemで追加していく方法だ。

 例によってカンでデータを入れてみる。

var dp:DataProvider = new DataProvider();

for ( var i:uint = 0; i < 2; i++ ) {
	dp.addItem( "label" + String( i ) );
}

 エラーは起きないけど項目に文字列がそのまんま追加されるようで、dp.getItemAt( 0 )で追加した文字列がそのまま返ってくる。

var dp:DataProvider = new DataProvider();

for ( var i:uint = 0; i < 2; i++ ) {
	dp.addItem( <label>labelA</label> );
}

 これもXMLがそのまま登録されている…てかaddItemって内部のArrayにpushしてるだけなんじゃ…
 いろいろと値を入れてみたけど、どうも大まかにはそうみたい。結局、使う時にlabelプロパティならlabelプロパティに反応する値ならいい訳で、中にどんな値が入っているかは関知しないという立場のよう。
 ということは…

var dp:DataProvider = new DataProvider();

for ( var i:uint = 0; i < 2; i++ ) {
	dp.addItem( <item label="labelA"/> );
}

 なるほど、これだと"@label"指定だから取れない、と。
 コンストラクタとは、解釈のしかたが違うんですなー。
 つまり、こんな感じに最初から整った値を渡さないといけないと。

var dp:DataProvider = new DataProvider();

for ( var i:uint = 0; i < 2; i++ ) {
	dp.addItem( <item><label>labelA</label></item> );
}

 当然、Object型で渡しても良い。

var dp:DataProvider = new DataProvider();

for ( var i:uint = 0; i < 2; i++ ) {
	dp.addItem( { label:"labelA" } );
}

 なるほどなるほど。
 fl.data.SimpleCollectionItemを使ってもいい。

var dp:DataProvider = new DataProvider();

for ( var i:uint = 0; i < 2; i++ ) {
	var sc:SimpleCollectionItem = new SimpleCollectionItem();
	sc.label = "label" + String( i );
	dp.addItem( sc );
}

 SimpleCollectionItemを使うメリットは、よー分からん。コンストラクタでlabelとdataを渡せる訳でなし。特別なメソッドがある訳でなし。これ使ってるとlabelとdataが含まれているという事が明示的になるぐらいか?

大体分かったDataProvider

 結局リファレンスは斜め読みだけど、だいたい分かった。
 次回からまた引き続き、UIコンポーネントを使っていってみよう。

 今日はここまで。


2011-02-13