サイトトップ

Director Flash 書籍 業務内容 プロフィール

Macromedia Flash非公式テクニカルノート

MovieClipに定義したクラスからコンポーネントを設定したい

ID: FN0510007 Product: Flash

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日


Copyright © 2001-2006 Fumio Nonaka.  All rights reserved.