クレラップミキサー クレラップとキチントさん ローカルエリア接続・無線LANをコマンドラインから有効/無効にする方法
4月 30

ずばり、コンポーネントの初期化の話なのですが、正味、これで3日はツブしました。頭悪くて済みません。

以下のようなflaファイルがあったとします。
compcheck.png

ステージに、
ns : NumericSteper
ta : TextArea
ti : TextInput
コンポーネントが配置され、それぞれ、コンポーネントインスペクタで、初期値を設定しています。
これをドキュメントクラスからアクセスしたかったんですが、うまく行かず、かなり試行錯誤しました。

まず、普通にドキュメントクラスのコンストラクタから、

trace(ti.text)

と、traceしてみたのですが、何も表示されません。空です。
コンポーネントインスペクタで文字を入れてるにもかかわらず、値が取得できません。
ただし、tiのインスタンス自体は生成されています。

AS2.0の頃にも、実は同じような問題があり、要するに、コンポーネント(ムービークリップ)がロードしきってないというか、初期化が完了してないうちにプロパティにアクセスしても、値が取得できない、ということです。

これはコンポーネントに限らず、ムービークリップや画像などでも同じです。

コンポーネントの場合、ステージに配置してるので、ドキュメントクラスのコンストラクタが呼び出された時点で、すぐにプロパティにアクセスできると信じ込んでいましたが、、実はダメでした。
(このあたりって、マニュアルのどこに書いてるのか、、つか、書いてないよねぇ)

そこで僕が考えたのは、AS2.0のように、何フレームか遅らせてアクセスする、という原始的なものでした。
Spark projectのcommandsまたはChainを使って、コンストラクタ呼び出し後、100ms後にコンポーネントにアクセスするという方法です。
実際、これはうまくいきました。
(※Chain初めて使ったけど、これスゴイね。便利そう。Commandsも負けず劣らず便利そう。ありがたや~)

ただ、あまりに稚拙というか、その場しのぎで、さすがにコレが最適な解じゃないよな、と続けて調べたところ、

  • Event.RENDER
  • Event.ADDED_TO_STAGE

というイベントを用いたらいいんじゃない・・・かな?と。

マニュアル読んでもあまり詳しいことは書いておらず、コンポーネントの初期化が完了した時点で、どちらのイベントが発生するのかがわかりません。
また、コンポーネントが複数ある場合、できれば全てのコンポーネントの初期化が完了した時点で、次の処理をしたい。

コンポーネントのインスタンスに、上記2つのイベントをAddEventListnererして確かめたところ、RENDERは発生するが、ADDED_TO_STAGEが発生しない(この時点では理由はわからなかったが、後でわかった)

そこで、コンポーネントのインスタンスを複数渡して、インスタンスの数だけEvent.RENDERが発生したらコールバック関数を呼ぶ(またはdispatch)オリジナルのクラスを作ってみた。

一見、うまく行ったが、どうもしっくりこない。微妙にタイミングがずれるような気がする。

そこで、もう一方のEvent.ADDED_TO_STAGEを調べたところ、コレはコンポーネントやムービークリップのインスタンスに対して起きるイベントではなく、それらが乗っかっているDisplayObjectに対して発生する模様。

そこで、ドキュメントクラス自信に、このイベントを割り当て、試してみた。以下がサンプルコードです。
[as]
package {
import fl.controls.NumericStepper;
import fl.controls.TextArea;
import fl.controls.TextInput;
import flash.display.MovieClip;
import flash.events.*;

/**
* …
* @author Default
*/
public class componentLoad extends MovieClip{

public var ti:TextInput;
public var ta:TextArea;
public var ns:NumericStepper;

/**
* コンストラクタ。
*/
public function componentLoad() {
trace(”first”);
trace(”ti:” + ti.text);
trace(”ta:” + ta.text);
trace(”ns:” + ns.value);

this.addEventListener(Event.ADDED_TO_STAGE, init);
}

private function init(e:Event):void {
// 念のため消しておく。
removeEventListener(Event.ADDED_TO_STAGE, init);
trace(”second”);
trace(”ti:” + ti.text);
trace(”ta:” + ta.text);
trace(”ns:” + ns.value);
}
}
}
[/as]
出力結果は、

first
ti:
ta:
ns:1
second
ti:テキストインプットでーす
ta:ActionScript^(TM) クラスのドキュメントには、(略)
ns:1234

と、コンストラクタの時点ではアクセス出来てないプロパティ(コンポーネントインスペクタで設定した値)に、ADDED_TO_STAGEイベント時には、ちゃんとアクセスできてました。

もっと複雑なケースの場合は、うまく行かないかもしれませんし、イベントの使い方が間違ってるかもしれませんが、勉強のためコード晒しました。

添削・指摘大歓迎です!

Popularity: 16% [?]

written by ANN

add to hatena hatena.comment (4) add to del.icio.us (0) add to livedoor.clip (1) add to Yahoo!Bookmark (0) Total: 5

2 Responses to “[AS3.0]コンポーネントインスペクタの値を取得する方法”

  1. joy-pop Says:

    最近ようやくAS3を始めてみましたー。
    検証してみたんですが、ACTIVATE、RENDERでもいけました。
    もしくは各DisplayObjectごとにADDEDでリスナーを…(略)、これ面倒くさいけど確実かも。
    名前からしてADDED_TO_STAGEがいいっぽいですなー。
    ただ、RENDER、ADD_TO_STAGEにはFlashPlayerの方にバグがあるそうです。

    [参考]
    http://level0.cuppy.co.jp/2008/02/as3gotoandstopeventrender.php

    コメ入れるのにメルアドも必須になってるです…。

  2. ANN Says:

    最近、しばらくAS3さわってないのですでに忘れ気味ですが、、、
    ACTIVATEは、マウスがFlashの外に出て、戻ってきた時にも発生するので、swf読み込み時の初期化という意味では、ちょっと違うんですよねー

    RENDERは、場合によって、何度かコールされる可能性があったと思います。

    コンポーネントに限らずですけど、インスタンスが初期化完了したかどうか確認しないといけないのが面倒なんですよー

    http://www.libspark.org/htdocs/as3/thread-files/document/
    これとか使えば、オブジェクトの初期化完了後の処理とかをわりと
    簡単に書けるんじゃないかと思ってるんですが、まださわれてない・・・

    RENDERとADD_TO_STAGEのバグは、意味がよくわからなかったのと、まぁ、該当する人は少ないだろうと思うので無視してます(^^;;;

    とにかく、いろんなものが非同期になるってのは、非常に面倒だなーと思いました。その点、PHPはシンプルだから楽っすー

    コメントのメアドの件、失礼しました。設定直しました~

Leave a Reply