本記事中のサンプルを表示するには最新のFlashPlayer9が必要です(本稿執筆時点では【9,0,28,0】が最新)。こちらから最新のFlashPlayer9をインストールしてください。また,インストール後はブラウザの再起動が必要です。インストールされているFlash Playerのバージョンを確認するにはこちら

 今回は前回に続いて,「ウィザード形式に顧客情報を入力する」サンプル・アプリケーション開発の後編をお届けします。

MXMLコンポーネントを使う

 前回MXMLコンポーネントの作成方法と,作成した各画面コンポーネントについて説明しました。では,このMXMLコンポーネントを使用するにはどうすれば良いのでしょうか? それは「main.mxml」の2行目に記述されています(図1)。

図1●MXMLコンポーネント用ネームスペースの宣言
図1●MXMLコンポーネント用ネームスペースの宣言
[画像のクリックで拡大表示]

 「xmlns」属性というのはXMLの構文で,使用するネームスペース(*1)を宣言するために使用されます。次の「dc」というのはユーザー自身が定義できるネームスペースの識別子になります。ここでは「Display Component」を略して「dc」としてみました。ユーザー自身が決めるので何でも良いわけですが,先頭に数字をつけることはできません。また,複数のネームスペースを宣言する場合は重複しないようにしなければなりません。さらにActionScript3同様に大文字と小文字を区別しますので「dc」と「DC」は違うネームスペースとして扱われますので注意してください。

 「dc」ネームスペースにセットされている「dsp.*」というのはパッケージ(package)名になります。前回のMXMLコンポーネントの説明でこのパッケージというのは一度も出てきませんでした。どこで宣言されているのでしょうか? それはソース・フォルダの構造からFlexBuilder2のコンパイラが自動的に設定します。今回のサンプルではソースルート・フォルダ「src」直下の「dsp」というフォルダにすべてのMXMLコンポーネントが配置されていますので,各MXMLコンポーネントは「dsp」パッケージに所属することになります(図2)。

図2●フォルダの構造
図2●フォルダの構造

 MXMLコンポーネントはファイル名がクラス名になります。つまり,サンプルの「BasicInfo.mxml」はActionScript3では図3のように定義されるわけです。

図3●ActionScript3における「BasicInfo.mxml」の定義(実際はBasicInfo内部で使用するクラスの「import」がパッケージとクラス宣言の間に多数存在します)
図3●ActionScript3における「BasicInfo.mxml」の定義(実際はBasicInfo内部で使用するクラスの「import」がパッケージとクラス宣言の間に多数存在します)

 実際にMXMLコンポーネントを使用しているコードは87行目~92行目(図4)になります。使用方法はいたって簡単で「ネームスペース識別子:クラス名」(半角コロンで区切る)になります。もちろん,2行目の「xmlns」の値を変更した場合は使用個所すべて変更する必要がありますので,命名時は注意してください。ちなみにMXMLファイルで宣言した「dc」というネームスペース名はMXMLから変換されたActionScript3には微塵も出てきません。つまり,「xmlns」属性はMXMLファイルにおけるコーディングを助けるための機能です。

図4●MXMLコンポーネントを使用している行
図4●MXMLコンポーネントを使用している行
[画像のクリックで拡大表示]

 では,「xmlns:mx="http://www.adobe.com/2006/mxml"」というのは何でしょうか? これについてはコラム1をご覧ください。

キーイベントを処理する

 ブラウザベースのWebアプリケーションとデスクトップ・アプリケーションというのはよく比較されます。そこで比較項目の一つとしてあがるのが「キーイベント」です。Flexで開発されたWebアプリケーションも例外ではありません。

 「Application」クラスの「keyDown」イベント(3行目)に「keyDownControll」関数を割り当てています(図5)。

図5●keyDownイベントの設定(関数の引数「event」についてはこちら*2)
図5●keyDownイベントの設定(関数の引数「event」についてはこちら*2

 実際の動きを確認するためにデバッグ実行してみます。まず,デバッグ実行中のキーイベントで停止させるために51行目の「keyDownControll」関数の定義行にブレークポイントを設定します(図6)。ブレークポイントの設定方法は行番号(*3),またはその左側の部分をダブルクリックすることでOn/Offすることができます。

図6●「keyDownControll」関数にブレークポイントを設定する
図6●「keyDownControll」関数にブレークポイントを設定する
[画像のクリックで拡大表示]

 ツールバーのデバッグボタンをクリックし,デバッグ実行します(図7)。

図7●デバッグ実行ボタン
図7●デバッグ実行ボタン

 起動したFlexアプリケーションのボタン以外の部分をクリックし,「Tab」キーを一度押します。すると,図8のように「Debug Child Model」ボタンにフォーカスが移動します。ここでもう一度「Tab」キーを押します。すると,デバッグ実行が図9のように51行目の「keyDownControll」関数で一時停止します。

図8●「Debug Child Model」ボタンにフォーカスがある状態
図8●「Debug Child Model」ボタンにフォーカスがある状態

図9●「keyDownControll」関数で停止
図9●「keyDownControll」関数で停止
[画像のクリックで拡大表示]

 図10の「ステップオーバー」ボタンを2回クリックすると図11のように54行目まで進み,コンソールビューには「9」というTabキーを表すキーコードが出力されます(図12)。

図10●ステップオーバーボタン
図10●ステップオーバーボタン

図11●54行目まで実行
図11●54行目まで実行
[画像のクリックで拡大表示]

図12●コンソールビューに出力されたキーコード
図12●コンソールビューに出力されたキーコード

 次に「再開」ボタン(図13)をクリックしてデバッグ実行を再開します。そして,もう一度「Debug Child Model」ボタンにフォーカスがあたるようにFlexアプリケーションのボタン以外の部分をクリックし,「Tab」キーを一度クリックします。今度は「F11」キーを押します。

図13●デバッグ実行の「再開」ボタン
図13●デバッグ実行の「再開」ボタン

 すると,どうでしょう。Internet ExplorerでもFirefoxでも全画面表示に切り替わりブレークポイントには止まりませんでした。これはブラウザがキーイベントを処理してしまいFlexアプリケーションまでイベントが飛んでこないためです(もう一度「F11」キーを押すと通常の画面に戻ります)。しかし,別の方法で実現できるかもしれません(コラム2を参照)。

画面切り替えの役目を果たす「ViewStack」

 ViewStackコンポーネント(*4)については別の機会に詳しく説明するとし,ここではどのように使用しているかを説明しましょう。ViewStackは図14のようなレイヤー構造で子オブジェクトを管理しています。

図14●ViewStackのレイヤー構造
図14●ViewStackのレイヤー構造

 レイヤー構造は子オブジェクトが追加された順になり,サンプルではソースコード行の上から下に子オブジェクトは追加されます。そして,「selectedIndex」属性でセットされた値のレイヤーの子オブジェクトが表示されます(初期値ゼロ)。この"表示"の仕組みですが,レイヤー構造は変わりません。では,どのように表示を切り替えているのでしょうか? Flexでは,ViewStack内部で選択されたインデックスのレイヤーの子オブジェクトだけを「visible=true」にすることで画面表示を切り替えています。

 サンプルでは「次へ」ボタンの「click」イベントに「goNextView」関数を,「戻る」ボタンの「click」イベントに「goPreviousView」関数を関連付けてViewStackの「selectedIndex」を加算・減算して画面を切り替えています。「goPreviousView」関数では「selectedIndex」の値がゼロ(最初の画面)より大きければ減算するロジックです。また,「goNextView」関数では現在選択されているインデックスが最大インデックス値(子オブジェクトの数 - 1)よりも小さい場合に加算するロジックです(「子オブジェクトの数」は「numChildren」属性に格納されています)。

 それぞれの関数内で「enabledButton」関数をコールしています。これはユーザビリティ的な配慮で,最初の画面(selectedIndex == 0)では「戻る」ボタンは押せないほうが良く,逆に最後の画面(selectedIndex == numChildren - 1)の場合は「次へ」ボタンは押せないほうが良いからです。もちろん,「enabledButton」関数の中身を「goNextView」関数・「goPreviousView」関数に埋め込んでも問題は無いのですが,分けたほうが見やすいと思い分けました。

 では,MXMLの実装コードを見てみましょう(図15)。

図15●ViewStackの実装コード
図15●ViewStackの実装コード
[画像のクリックで拡大表示]

 「historyManagementEnabled」属性については前回紹介しました履歴管理機能を有効・無効にする属性で,ViewStackだけ履歴管理機能の初期値が「false」=無効になっていますので,明示的に「true」=有効にする必要があります。「change」イベントに先ほど紹介した「enabledButton」関数を割り当てています。なぜでしょうか? それは履歴管理機能でブラウザの「戻る」・「進む」をクリックされた場合に対応させるためです。

 つまり,履歴管理機能によって「selectedIndex」を変更された場合に,この「change」イベントが呼び出されるからです。試しに,最初の画面で「次へ」ボタンをクリックし,ブラウザの「戻る」ボタンをクリックすると,Flexアプリケーションの「戻る」ボタンが無効になると思います。

 次にViewStackとその子オブジェクトそれぞれに「creationComplete」イベントを設定しデバッグ情報(trace)をコンソールビューに出力するようにしています。これはイベントの流れを知るために実装しました。

 イベントの発生順序は子オブジェクト→ViewStackです。ただし,実行時にすべての子オブジェクトで「creationComplete」イベントが発生するのではなく,表示される子オブジェクトにだけ発生します。また,デバッグ実行でコンソールビューを見ながら「次へ」・「戻る」ボタンをクリックするとわかるように,子オブジェクトを表示する毎に「creationComplete」イベントが発生します。

 前回説明したように,画面を切り替えるたびに画面コンポーネントを生成しているわけではありません。一度でも画面コンポーネントを表示すると作成済み状態になりますので,ちょっと奇妙な動作です。これはViewStackのようなコンテナ系クラスが子オブジェクトの作成済み状態を管理していないためです。そのため「selectedIndex」で選択された子オブジェクトから送出される「creationComplete」イベントで作成済み状態を判定するしかないのです。

各画面の「Model」

 各画面コンポーネントに「mx:Model」を定義しています。これ自体はユーザー定義オブジェクトです。重要なのはModel内の各項目に記述している「{}」中括弧です。この中括弧表記をすることでFlexFramework2の「Binding」機能(*5)が利用できるのです。

 「Binding」機能とは何でしょう? 実はこの機能だけで1回分の記事がかけてしまいそうなほどボリュームがある機能で,かつ,ちょっと難解です。しかし,非常に便利な機能です。一言で言ってしまうと「変数を監視・連携させる仕組み」です。では,実際にどういうものなのかサンプルを動かして確認してみましょう。

 サンプルの2画面目の「基本情報」画面を開きます。まず,ここで前回説明しなかった「Debug Child Model」ボタンをクリックしてください。すると,画面下のTextAreaに「BasicInfo.mxml」で定義したModelオブジェクトが文字列で出力されます(*6)。

 次に「氏名(フリガナ)」入力エリアに実際にご自分の氏名カナを入力し,もう一度「Debug Child Model」ボタンをクリックしてください。どうでしょうか?「lastKana」変数と「firstKana」変数に入力した文字列が出力されていると思います。「BasicInfo.mxml」にはどこにも"代入式"は存在しません。これが先ほど説明した「Binding」機能です。

 具体的に説明しますと,「BasicInfo.mxml」の「mx:Model」に「<lastKana>{lastKanaInput.text}</lastKana>」の中括弧記述があります。この記述で「lastKanaInput」の「text」属性を「model.lastKana」変数に連携させています。つまり,「lastKanaInput」の「text」属性が変更されると,自動的に「model.lastKana」変数の値も変更されるわけです。

 「Binding」機能はもちろん「Model」以外にも適用することが可能です。この「Binding」機能を活用した「Cairngorm」と呼ばれる開発フレームワークも存在します(*7)。それほど有用な機能ですので,ぜひともじっくりと時間をかけて会得してください。

 次に「確定」ボタンについてです。これは「main.mxml」のModelオブジェクトを出力しています。その定義は図16を見てみましょう。

図16●「main.mxml」のModelオブジェクトの定義
図16●「main.mxml」のModelオブジェクトの定義
[画像のクリックで拡大表示]

 見てのとおり,それぞれの子画面コンポーネントのModelオブジェクトをバインド(Binding)しているだけです。ここでお伝えしたいことは図17です。

図17●各Modelオブジェクト変数のデバッグ(ここで「this」は「main.mxml」=アプリケーションそのものを現します)
図17●各Modelオブジェクト変数のデバッグ(ここで「this」は「main.mxml」=アプリケーションそのものを現します)

 FlashPlayer9の仕様は公開されていませんが,ガーベジ・コレクション機能が搭載されていることはFlex2のヘルプに掲載されています。なので,ActionScript3でも直接メモリーを操作することはできず,Flash Player自身がオブジェクトとその使用メモリーを管理していると思われます。

 図17に表示されている@マーク以下の文字は,その参照値だと思われます。図17をよく見ていただくとわかると思いますが「this.basic.model」(基本情報画面のModelオブジェクト)と「hits.model.basicInfo」(「main.mxml」のModelオブジェクトの項目)は同じ参照値を指しています。つまり,「<basicInfo>{basic.model}</basicInfo>」という「Binding」は,実行時に同じランタイムオブジェクトを参照することを意味しているのでは?と推測しています。

 以上で,第7回・第8回と2回にわたりましたサンプル・アプリケーションの説明は終了です。

【コラム1】「xmlns:mx="http://www.
adobe.com/2006/mxml"」について

 これについては「第12回 Flex2勉強」でFlash/Flexマスターの上野氏が紹介してくれました。ただ,少し濃い内容になりますので,このコラムにて軽く説明したいともいます。

 「xmlns:mx」までは本文でも紹介した通りなのですが,この「http://www.adobe.com/2006/mxml」はパッケージ名ではありません。では,どこで定義されているのでしょうか?

 実はSWCライブラリの中に含まれています。そして,このSWCライブラリはファイルの拡張子こそSWCですが,本当はただのZIPファイルです。なので,「${FlexBuilder2 インストールルート}\Flex SDK 2\frameworks\libs」フォルダ直下にある「framework.swc」をコピーし違うフォルダに貼り付け,拡張子を「ZIP」に変更します(図1)。

図1●「framework.swc」を「framework.zip」に変更(必ずコピー&ペーストで作業フォルダにコピーしてからファイル操作をしてください)
図1●「framework.swc」を「framework.zip」に変更(必ずコピー&ペーストで作業フォルダにコピーしてからファイル操作をしてください)
[画像のクリックで拡大表示]

 この「framework.zip」を解凍すると図2のようになります。

図2●解凍されたファイル一覧
図2●解凍されたファイル一覧
[画像のクリックで拡大表示]

 図2で赤線で囲まれた「catalog.xml」をメモ帳などで開いてみると,図3のように各コンポーネントのフルパスのクラス名,コンポーネント名が定義されており,それが「uri」属性で「http://www.adobe.com/2006/mxml」に結び付けられています。

図3●SWCライブラリのカタログファイル
図3●SWCライブラリのカタログファイル
[画像のクリックで拡大表示]

【コラム2】「Apollo」(開発コードネーム)について

 本文でも説明しましたとおり,現状のFlexアプリケーションではブラウザが処理してしまうキーイベントを割り当てることができません。しかし,2007年後半に「Apollo」が登場する予定であると1月17日に開催されたアドビシステムズの「2006年度の業績および2007年度の事業戦略についての説明会」にて発表されました。

 Apolloについては本連載の「特別レポート」でも少し紹介しましたが,FlexBuilder2でも開発が可能なデスクトップ・アプリケーション環境です。また,すでに作成済みのFlex2アプリケーションも容易にApolloアプリケーションに修正できるのでは,という可能性を「第12回 Flex2勉強」にてクラスメソッドの横田氏(代表取締役社長)がいち早く紹介してくれました。

 デモでは「mx:Application」の部分を「mx:ApolloApplication」に変更するだけでWebアプリケーションがデスクトップ・アプリケーションに変わりました(あくまでベータ版なのでリリース時には変更される可能性があります)。著者も「Apollo」には大きな期待を抱いていますので,リリースが非常に楽しみです。