2章 MXMLでのアプリケーション開発

この章では、いろいろなコンポーネントを利用した例を通じてMXMLに慣れることが目的なのでしょう。

この章を読んでMXMLを記述する上で注意することをピックアップしてみました。

エンコードUTF-8

MXMLファイルの文字コードUTF-8XMLの宣言でもちゃんと記述すること。お約束。
MXMLファイルの先頭には、下の記述をすること。*1

<?xml version="1.0" encoding="utf-8"?>

コンパイル

Flex SDK使っている人は下のような感じでしょうか?

mxmlc --show-actionscript-warnings=true --strict=true hoge.mxml

で、『Flex 2 アプリケーションの構築および展開ガイド』(http://www.adobe.com/support/documentation/jp/flex/)にさらに詳細がかいてあるとのことなので、寄り道してみます。

Flexにはアプリケーションコンパイラ(mxmlc)というものとコンポーネントコンパイラ(compc)と言うのがあるらしい。前者がSWFファイル、後者がSWCファイルを生成するものと覚えればいいのかな?
ライブラリ作るときはcompc、実際に動くものはmxmlcと言うことですね。

次にmxmlcの動作ですが、デフォルトのコンパイラ設定はSDK配下にあるflex-config.xmlファイルに記述されているようです。ここを自分用にカスタマイズしてもいいみたいですが、たぶんプロジェクトごとに作成し、それをmxmlcを実行する際にオプションで渡してあげるのがスマートですね。

さて、オプションにはどんなものがあるかを見てみましょう。私なりに、ちょっと惹かれるものを表にしてみました。

オプション 内容
debug=true デバッグSWF生成。verbose-stacktraceもtrueにしてされるらしい
default-script-limits max-recursion-depth max-execution-time max-recursion-depthがスタックオーバーフローの制限値。デフォルト1000、max-execution-timeはイベントハンドらの最長実行時間(秒)。これを過ぎるとハングしたとみなされるらしい。61以上には指定できないようです。あまり触らないほうがいいのでしょうかね。
link-report filename 何をリンクしたのかを指定したfilenameファイルに出力してくれるらしい
load-config コンパイラオプションを定義する設定ファイルの場所を指定する。
locale string SWFにパッケージ化されるローケール(en_EN)とかを指定する。ローカライズするときはいるんでしょうね
optimize=true ActionScriptオプティマイザを有効にするらしい。これってどれだけ公かあるんだろう。デフォルトfalseだから、あまり使わなくてもいいんだと思う。*2
output filename 出力先ですね。
services filename "service-config.xml"ファイルの場所を指定。今は良く分からないけど、そのうち出てくるでしょう。
show-actionscript-warnings=true ActionScriptに関する警告を表示します。
show-deprecation-warnings=true Flex非推奨コンポーネントに対する警告でしょうか。
source-path path-element [...] ソースのディレクトリを指定する。ワイルドカードでサブディレクトリ、ファイルを指定することもできるらしい
strict=true 未定義プロパティ、関数呼び出しを出力します。コンパイル時型チェックもしてくれます。普通は必須でしょうね。デフォルトもtrueです。
theme filename [...] アプリケーションが使用するテーマファイルのリストを指定します。CSSCSSが含まれているSWCファイルを指定できます。
use-network=true ネットワークサービスを利用できるようにします。デフォルトtrueですね。
use-resource-bundle-metadata=true リソースバンドルを有効にします。デフォルトもtrueです。
verbose-stacktraces=true 行番号を含むソースコードを生成します??って説明おかしくない?たぶん、SWFにソースコードの情報も入れるということだと思います。デフォルトfalseなので、つけておいたほうがいいのかな?
warnings=true すべての警告を出力します。デフォルトtrueですね。
keep-generated-actionscript=true 中間ファイルとして出力されるActionScriptファイルを残します。

ちなみにこれらを指定するときは"--"を前につけます。上のmxmlcの例のようにね。

MXMLのタグはActionScriptのクラス、プロパティに対応

ということで、早速オプション"keep-generated-actionscript"を使って確認してみましょう。

こいつを"Hello.xml"としてActionScriptにして確認。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:explorer="*" width="100%" height="100%" pageTitle="ハロー">

    <mx:Panel id="panel1" title="アプリケーション">
        <mx:Label id="label1" text="ハロー1" />
        <mx:Label text="ハロー2" />
    </mx:Panel>

</mx:Application>

すると・・・。mxmlをおいてあるフォルダにgeneratedというフォルダが作られ、その中にいっぱいActionScriptを作ってくれました。(計38ファイル)

だけど、これを確認するにはHello-interface.asを確認すればいいみたい。
この中身は下のような感じ。

package 
{
import flash.accessibility.*;
import flash.debugger.*;
import flash.display.*;
import flash.errors.*;
import flash.events.*;
import flash.external.*;
import flash.filters.*;
import flash.geom.*;
import flash.media.*;
import flash.net.*;
import flash.printing.*;
import flash.profiler.*;
import flash.system.*;
import flash.text.*;
import flash.ui.*;
import flash.utils.*;
import flash.xml.*;
import mx.binding.*;
import mx.containers.Panel;
import mx.controls.Label;
import mx.core.Application;
import mx.core.ClassFactory;
import mx.core.DeferredInstanceFromClass;
import mx.core.DeferredInstanceFromFunction;
import mx.core.IDeferredInstance;
import mx.core.IFactory;
import mx.core.IPropertyChangeNotifier;
import mx.core.mx_internal;
import mx.styles.*;
import mx.controls.Label;
import mx.core.Application;

public class Hello extends mx.core.Application
{
	public function Hello() {}

	[Bindable]
	public var panel1 : mx.containers.Panel;
	[Bindable]
	public var label1 : mx.controls.Label;

	public var _bindingsByDestination : Object;
	public var _bindingsBeginWithWord : Object;


}}

idを指定したものについては、ちゃんとpublicになっていますね。
しかもタグがネストしていても、関係なしですね。だからidは1MXMLで一意にしなければならないのですね。
あとは指定しなかったものはここでは現れてこないですね。

ちなみにidが重なったときのエラーはこんな感じ

Hello.mxml(6): Error: identifier 'label1' used more than once.

うん、ぶつかってるところの行数と名前もちゃんと出してくれますね。分かりやすい。

Flexにおける基本用語

GUIをやってる人にはなんとなくわかるけど、やってない人にはわかりづらい用語を見て見ます。

コントロール
ボタン、テキストフィールド、リストボックスなどフォーム要素です。
コンテナ
コントロールや、他のコンテナを収める画面上の矩形領域です。
レイアウトコンテナ
ユーザインターフェースのレイアウトを指定するもの。HBox/VBox/Gridなどがあるらしい。
ナビゲータコンテナ
ナビゲーションの制御。TabNavigator/ViewStackなどがあるらしい。
Containerクラス
すべてのFlexの基本クラス
スキニング
コンポーネントのグラフィックエレメントを修正、置換することで概観を変更する処理。
テーマ
スキンを格納するファイルのこと。
エフェクト
短い時間内にコンポーネントに変化を与えること。

コンポーネント間のデータバインディング

コンポーネントが他のコンポーネントの中の値を見に行くときには"{}"を使うみたいです。

下のような感じですね。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:explorer="*" width="100%" height="100%"
    pageTitle="コンポーネント間のデータバインド">

    <mx:Panel title="アプリケーション">
        
        <mx:TextInput id="textInput1" text="こんにちは" />
        
        <mx:Panel>
            <mx:TextArea id="textArea1" text="{textInput1.text}" />
        </mx:Panel>
        
        <mx:Button label="Bye" click="textInput1.text='ばいばーい';" />
    </mx:Panel>

</mx:Application>

基本的にはコンポーネントにはidを振ってあるので、それを使ってアクセスすればいいみたいです。しかも、一意なのでネストの関係とか一切気にしなくていいみたいですね。

データモデルとデータの検証

Modelタグでデータを一時的に格納する領域を作ることができるみたい。実際にはこれを使うよりも、ActionScriptで箱を用意するほうがいいと思う。ただその場合、データのバインドをどうするんだろう。おいおいですね。

で、さらに、入力されたデータを検証することもできます。これには、各種Validatorタグを用意してあげればいいみたいです。

で、ソースは以下のような感じ

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:explorer="*" width="100%" height="100%" pageTitle="ハロー">

    <mx:Model id="model">
        <info>
            <mesg>{mesgInput.text}</mesg>
            <phone>{phoneInput.text}</phone>
            <email>{emailInput.text}</email>
        </info>
    </mx:Model>

    <mx:StringValidator id="stringValidator" source="{mesgInput}"
        property="text" minLength="3" maxLength="5" />

    <mx:PhoneNumberValidator id="phoneNumberValidator"
        source="{phoneInput}" property="text">
        <mx:invalidCharError>入力しちゃいけない文字があるよ</mx:invalidCharError>
        <mx:wrongLengthError>10桁入力して</mx:wrongLengthError>
    </mx:PhoneNumberValidator>
    
    <mx:EmailValidator id="emailValidator" source="{emailInput}" property="text" />

    <mx:Panel title="入力チェック">
        <mx:TextInput id="mesgInput" text="Hello" />
        <mx:TextInput id="phoneInput"
            text="This isn't a valid phone number." />
        <mx:TextInput id="emailInput" text="me@somewhere.net" />
    </mx:Panel>

</mx:Application>

Validatorもいろいろあるみたいだけど、それは今後の章で出てくるみたいだから、深追いはしません。

その他

RPCサービスとかいろいろあるのですが、そのうち出てくると思うので今回はスルーします。

*1:MXMLでBOMつけた場合、の場合どうなるか調べること

*2:パフォーマンスチェック