株式会社antsのホームページへようこそ。

FlexとActionScript 3でガジェットを作る!<第3回>

0
Posted in Lab. By antsinc

しばらく間が開きました。みなさん、Flexと楽しく過ごしていますか?

前回までで、コントロールを貼り付けてイベントをハンドルするメソッドを割り当てる方法が分かりました。これは何でもかんでもコントロールのMXMLタグ内に記述する方式です。これはこれで便利な書き方なのですが、MXML自体の構造の明快さが失われます。そこで今回は、ActionScript部分をMXMLファイルの外に追い出してしまいましょう。

イベント用のスクリプトをUIコントロールから追い出す

スクリプト部分をMXMLファイルから追い出すには、外部ASファイルを作成します。[Navigator]ペインのプロジェクトを右クリックし、[New]―[ActionScript File]を選択し、適当な名前を付ければASファイルが作成されます。ファイル名は、クラス名が慣習的に大文字アルファベットで始まることから、小文字アルファベットで開始するのがよいでしょう。ここでは「eventHandlers.as」というファイル名にしておきます。

外部ASファイル化するということは、基本的には次の方針でコードをリファクタしていくことになります。

  • UIコントロールのイベント属性に直接ActionScriptの長いコードを書かない(外部関数の呼び出しだけにする)
  • <mx:Script>タグはなくさないが、細かいスクリプトを記述しない

このようなルールでMXMLを書き換えていきます。元になる前回の最終段階のMXMLは次のようなものでした。

前回のMXML

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    width="500" height="300">
  <mx:Button label="Test" id="testBtn01" labelPlacement="right" fontFamily="Courier New"
  fontSize="13" color="#ff8040" themeColor="#919cc4" fillColors="[#400080, #400080]"
  width="80" height="30" y="7" cornerRadius="4"
  mouseOver="popTxt01.text='mouseOver event occurerd.';popTxt01.visible=true;"
  mouseOut="popTxt01.visible=false;popTxt01.text='';" click="test();"
  horizontalCenter="0" icon="@Embed('ICON_test.png')"/>
  <mx:Text y="56" fontSize="18" fontWeight="bold" fontFamily="Courier New"
  color="#ffffff" width="400" id="popTxt01" textAlign="center" height="25"
  creationComplete="popTxt01.visible=false;" horizontalCenter="0"/>
  <mx:Script>
    <![CDATA[
      function test():void{
        popTxt01.text="click event occurerd.";
      }
    ]]>
  </mx:Script>
</mx:Application>

まずは最初のルールに適応できるようにイベントにアタッチしているスクリプトを<mx:Script>タグの中に置いてみましょう。ある程度の汎用化を考慮に入れて書き換えておくのがベターです。

イベントを簡素化するための関数化(リスト1)

<mx:Script>
  <![CDATA[
    public function initApp():void{
      popTxt01.visible=false;
    }
    public function btnClick(obj:Object):void{
      switch(obj.name){
        case 'testBtn01':
          popTxt01.text="click event occurerd.";
          break;
        default:
          break;
      }
    }
    public function btnOver(obj:Object):void{
      switch(obj.name){
        case 'testBtn01':
          popTxt01.text='mouseOver event occurerd.';
          popTxt01.visible=true;
          break;
        default:
          break;
      }
    }
    public function btnOut(obj:Object):void{
      switch(obj.name){
        case 'testBtn01':
          popTxt01.visible=false;
          popTxt01.text='';
          break;
        default:
          break;
      }
    }
  ]]>
</mx:Script>

これで、<mx:Script>を閉じた状態だと次のようなMXMLソースになるように書き換えます。

第一段階のMXML(リスト2)


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    width="500" height="300" creationComplete="initApp();">
  <mx:Button label="Test" id="testBtn01" labelPlacement="right" fontFamily="Courier New"
    fontSize="13" color="#ff8040" themeColor="#919cc4" fillColors="[#400080, #400080]"
    width="80" height="30" y="7" cornerRadius="4"
    mouseOver="btnOver(testBtn01);"
    mouseOut="btnOut(testBtn01);"
    click="btnClick(testBtn01);"
    horizontalCenter="0" icon="@Embed('ICON_test.png')"/>
  <mx:Text y="56" fontSize="18" fontWeight="bold" fontFamily="Courier New"
    color="#ffffff" width="400" id="popTxt01" textAlign="center"
    height="25" horizontalCenter="0"/>
  <mx:Script>
    ……(ここに上のスクリプトが入る)……
  </mx:Script>
</mx:Application>

イベントにアタッチしていたスクリプトが、すべて関数として実装しなおされて<mx:Script>タグの中に書かれていることが分かると思います。テキスト表示領域が初期段階で表示されないようにするには、前回までだと<mx:Text id=”popTxt01″>自体のcreationCompleteイベントに非表示にするコードを書きましたが、今回はアプリケーション全体の初期化フェーズで行うように、initApp()関数にまとめました。今後、アプリケーション全体の初期化段階で行うオブジェクトのイニシャライズはここで行うことにします。初期化用の記述があちこちに分散するのはデバッグが大変になりますからね!

ほかの関数では、すべてどのオブジェクトから呼び出されたかを引数としてしていしています。これにより、たとえばbtnClick()関数だとしたら、今後ボタン類が増えた場合でもこの一箇所でイベントをハンドリングできるようになります。一種のマネージャを用意したことになるので、これも拡張性を考慮したコーディングです。引数に文字列ではなくオブジェクトの参照を渡しているのは、今後、イベントが起きたオブジェクトを操作することが可能性としてあるため、switch~case文での拡張が楽になることからです。

スクリプト部分を外部AS化する

ここまで整理しておけば、あとは簡単な手順です。まず、あらかじめ用意しておいたeventHandlers.asファイルにリスト1のActionScript部分をカット&ペーストして保存します。その際に、インデンテーションがMXMLの状態のままなので、ASファイルを全選択しておき、Shift+Tabでインデンテーションを揃えてしまいましょう。

次に、ごっそりとスクリプトがいなくなったMXMLの<mx:Script>タグ部分を次のように書き換えます。

第二段階のMXML(リスト3)


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
    width="500" height="300" creationComplete="initApp();">
  <mx:Button label="Test" id="testBtn01" labelPlacement="right" fontFamily="Courier New"
    fontSize="13" color="#ff8040" themeColor="#919cc4" fillColors="[#400080, #400080]"
    width="80" height="30" y="7" cornerRadius="4"
    mouseOver="btnOver(testBtn01);"
    mouseOut="btnOut(testBtn01);"
    click="btnClick(testBtn01);"
    horizontalCenter="0" icon="@Embed('ICON_test.png')"/>
  <mx:Text y="56" fontSize="18" fontWeight="bold" fontFamily="Courier New"
    color="#ffffff" width="400" id="popTxt01" textAlign="center"
    height="25" horizontalCenter="0"/>
  <mx:Script>
    include "eventHandlers.as";
  </mx:Script>
</mx:Application>

だいぶスッキリしたことが分かると思います。この規模ではメリットがあまりない構成だと思うかもしれませんが、UIをメインにしたアプリケーションの構造部分はMXMLファイルに、ロジック部分は外部ASファイルにほぼ完全に分離できるメリットがあります。複雑なActionScriptを<mx:Script>タグ内に直接記述することによって可読性が下がると、アプリケーションのデバッグが非現実的になってしまいます。スクリプトの実験が済んだら、済んだユニットをどんどん外部ASファイルにカット&ペーストしていくと、視野を広く保ったままで開発できるでしょう。

さらにActionScript部分の完全分離を目指すなら、<mx:Script>sourceアトリビュートを追加し、属性値に.ASファイルのパスを記述します。閉じタグを不要にしてさらにソースコードをクリーンアップするために、<mx:Script> source=”eventHandlers.as” />とすることで、さらに開発中の視野が広がります。

それでは次回は、タイマーを使ってボタン アクションの制御に幅を持たせてみます。

Let’s Flex!

■今回作ったサンプルのMXMLとAS、SWFなど
FlexSample03.zip