Platform: All
Version: MX 2004 and above
UI Componentsのインスタンスを、MovieClipシンボル内に配置して利用したい場合があります。MovieClipのフレームアクションでコンポーネントインスタンスを設定するときには、コンポーネントを(UIObject.createClassObject()メソッドなどで)ダイナミックに配置しても、オーサリング時に予め配置しておいても、とくに問題はありません。ところが、MovieClipシンボルに[AS 2.0クラス]としてクラスを設定する場合、コンポーネントインスタンスの初期設定には注意すべき点があります。
1. ComboBoxにフレームアクションで項目を設定する
MovieClipシンボル内に予め空のComboBoxを配置し、項目はComboBox.addItem()メソッドを使ってダイナミックに設定してみます。MovieClipの第1フレームアクションには、つぎのスクリプトを記述します(スクリプト001)。MovieClipシンボル内のComboBoxインスタンス名は、existingComboBoxとします。
スクリプト001■MovieClip内のComboBoxに項目を設定するフレームアクション
import mx.controls.ComboBox;
// ComboBoxインスタンスexistingComboBoxを予め配置
var existingComboBox:ComboBox;
var nAmount:Number = 3; // ComboBoxに設定する項目数
// ComboBoxのイベントリスナー登録[*1]
existingComboBox.addEventListener("change", this);
// ComboBoxインスタンスに項目を設定
function init() {
for (var i:Number = 0; i<nAmount; ++i) {
existingComboBox.addItem("item"+i, i);
}
}
// ComboBoxからリスナーとして呼出されるコールバック関数
function change(eventObject:Object):Void {
var selectedValue:Number = eventObject.target.value;
trace(selectedValue); // 選択された項目のデータ(番号)を出力
}
init(); // 関数の呼出し
|
[ムービープレビュー]で確認すると、空のComboBoxにスクリプト(001)で項目が設定されます(図001)。項目を選択すると、[出力]パネルにはその項目の番号(0〜3)が表示されます。
図001■スクリプトで項目の設定されたComboBox
[*1] イベントリスナーには、別途のリスナーオブジェクトを作成せず、スクリプトを設定したMovieClipインスタンス自身(this)を登録しています。このMovieClipをスクリプトと合わせて、ちょうどコンポーネントのような「パーツ」として捉えるデザインです。スクリプトをクラスとして定義しようとする場合には、このデザインの方が移行しやすいでしょう。
|
2. MovieClipにクラスを定義してComboBoxを設定する
スクリプトをクラスとして定義し、MovieClipシンボルに設定してみます。MovieClipシンボルの構造には手を加えず、空のComboBoxを配置しておきます。したがって、ComboBoxの項目は、クラスから設定することになります。ところが、ComboBoxの設定をクラスのコンストラクタで実行しようとすると、処理が行われません。
クラスのコンストラクタからコンポーネントがどのような状態として認識されているか、確認のためのクラスを定義してみました(スクリプト002)。MovieClipにはmy_mcというインスタンス名をつけて、メインタイムラインに配置しました。
スクリプト002■クラスのコンストラクタからComboBoxの状態を確認
import mx.controls.ComboBox;
class UseComponent extends MovieClip {
var existingComboBox:ComboBox;
function UseComponent() {
init();
}
function init() {
trace(existingComboBox); // 出力: _level0.my_mc.existingComboBox
trace(existingComboBox instanceof ComboBox); // 出力: false
trace(existingComboBox instanceof MovieClip); // 出力: true
trace(existingComboBox.addItem); // 出力: undefined
}
}
|
[出力]結果を見ると、まずComboBoxインスタンスの存在自体は、パス(_level0.my_mc.existingComboBox)として表示されています。しかし、instanceof演算子の戻り値から、それはComboBoxのインスタンスとしてではなく、通常のMovieClipインスタンスとして認識されていることがわかります。したがって、今回利用しようとしたComboBox.addItemメソッドが存在せず、未定義値undefiendが出力されたのです。
MovieClipに設定したクラスのコンストラクタ関数は、インスタンス生成時に呼出されます。このとき、そのMovieClipシンボル内に配置されたコンポーネントインスタンスは、まだ初期化されていない状態のようです。したがって、そのコンポーネントのメソッドを呼出そうとしても、未定義のため呼出せないことになります。
MovieClipシンボル内に配置したコンポーネントの初期化を待って処理を行うには、MovieClipクラスから継承したMovieClip.onLoadイベントハンドラを使えばよいでしょう[*2]。クラスにonLoad()メソッドを定義して、その中でコンポーネントインスタンスに対する処理を記述します(スクリプト003)。
スクリプト003■MovieClipに予め配置したコンポーネントを設定するクラス
import mx.controls.ComboBox;
class UseComponent extends MovieClip {
var existingComboBox:ComboBox;
var nAmount:Number = 3;
function UseComponent() {
// init();
}
// function init() {
function onLoad() {
for (var i:Number = 0; i<nAmount; ++i) {
existingComboBox.addItem("item"+i, i);
}
existingComboBox.addEventListener("change", this);
}
function change(eventObject:Object):Void {
var selectedValue:Number = eventObject.target.value;
trace(selectedValue);
}
}
|
[*2] MovieClip.onLoadイベントハンドラメソッドを使うべき数少ない実用上の例です。クラスの通常の初期化の処理は,コンストラクタ関数に記述すれば足ります。また、フレームアクションやMovieClipアクションなど、クラスでなくムービー中に記述した場合、それらのスクリプトはMoiveClip.onLoadイベントがすでに発生した後に処理されるため、コールバック関数を設定しても呼出されません(「MovieClip.onLoadイベントハンドラメソッド」参照)。
|
3. UIComponentクラスを継承する
[コンポーネント]パネルのUI Componentsは、複数のクラスやMovieClipをベースにしたパーツから構成されているので、それらの初期化や設定のタイミングが設計上きわめて重要です。そのためFlash MX 2004から採用されたMacromedia Component Architectureバージョン 2では、UIObjectおよびUIComponentクラスが、コンポーネントの基本的な機能を提供し、その初期化・設定の管理を行っています。
UIObjectあるいはそのサブクラスのUIComponentを継承すると、コンポーネントを管理するための独自のイベントが呼出されます[*3]。描画の直前にはdraw()イベントが呼ばれますので、コンポーネントの表示内容を決める処理は、そのメソッド内で行うことができます(スクリプト004)[*4]。なお、UIObjectは、MovieClipクラスを継承しています。
スクリプト004■UIObjectを継承してdraw()メソッドでコンポーネントの設定を行う
import mx.controls.ComboBox;
// class UseComponent extends MovieClip {
class UseComponent extends mx.core.UIObject {
var existingComboBox:ComboBox;
var nAmount:Number = 3;
function UseComponent() {}
// function onLoad() {
function draw() {
for (var i:Number = 0; i<nAmount; ++i) {
existingComboBox.addItem("item"+i, i);
}
existingComboBox.addEventListener("change", this);
}
function change(eventObject:Object):Void {
var selectedValue:Number = eventObject.target.value;
trace(selectedValue);
}
}
|
[*3] UIObjectから呼出されるメソッド(イベント)については、Flash 8オンラインヘルプ[Flash コンポーネントガイド]> [コンポーネントの作成] > [ActionScriptクラスファイルの作成] > [コア関数について]をご参照ください。
なお、init()も、UIObjectから独自に呼出されるメソッドに含まれます。ですから、コンストラクタ関数から呼出すと、二重の呼出しになってしまうので注意しましょう。
[*4] draw()は、MovieClip.onLoadイベントよりも後に呼出されます。
|
_____
作成者: 野中文雄
作成日: 2005年10月21日