Home > Flex3

Flex3 Archive

[Flex]コンポーネントのサイズがゼロになる?

Frog on AIRさんのサイトで、こんな記事がありました。

オブジェクトのサイズを取得できない(AIR β2/β3)

記事の内容は、mx.controls.Butttonのインスタンスを生成した直後に、widthとheightの値を確認すると0になってしまう。というようなものです。

実際僕も何か作っているとき、同じような状況を何度も経験しました。
ホント大ハマリして、何時間も費やしたり・・・。
自分の備忘録も兼ねて、少しこのあたりを書き残しておきます。

クラスの種類
Flex2のリファレンスで説明されているクラスの中には、
純粋なActionScript3.0のクラスとFlex2のクラスの2種類があります。

純粋なActionScript3.0のクラスとは、
Array、Number、SpriteやTextFieldなどのクラスで、
importするときのクラスパスが、flash.~のものです。

対して、Flex2のクラスとは、
UIComponent、Button、Alert、PopUpManagerなどなど、
importするときのクラスパスが、mx.~のものです。

純粋なActionScript3.0のクラスというのは、
ActionScript3.0という言語でプログラミングをする場合には基本的に使えるクラスで、
FlexBuilder2でもFlashCS3でも使えるはずです。
一方Flex2のクラスというのは、
上記純粋なActionScript3.0のクラスを拡張(継承)したクラスで、
Flex2SDKのコンパイラでは一緒に提供されているだけです。
Flex2のクラスというのは、つまり、ActionScript3.0でプログラムする場合に、
使用できるオプション的なクラス郡になります。

例えばButtonクラスならSpriteを継承したクラスFlexSprite、
をさらに継承したUIComponentクラス、
をさらに継承したものがButtonクラスです。

Flex2のクラス
Flex2のクラスはFlexフレームワーク上で動作することを前提に作成されています。
つまりいくつかのフレームワークのルールに従う必要があるということです。

このルールのひとつとしてFlex2フレームワークを用いる場合には、
多くの便利なビジュアルコンポーネントを利用できるようになる代わりに、
独自のDisplayObjectを表示させたい場合には、
UIComponentクラスを継承しなければならないというルールがあります。
(IUIComponentインターフェースでもいいのかな・・・?)

UIComponentクラスでは、
コンストラクタでは最低限のプロパティとイベントリスナの初期化しか行いません。
(このため、インスタンス生成直後にはwidthなどは0になります。)
コンポーネントがDisplayObjectのツリー上にaddChildされるたあと
initialize()メソッドが呼ばれ、描画に必要なプロパティの一部がセットされます。
その後、実際に描画されるタイミングでupdateDisplayListというメソッドで、
レイアウトやサイズ等の値が計算され(ここでwidth等の値が確定します)、描画されます。
もちろんaddChildメソッドもoverrideして、子DisplayObjectを自身に追加する際には、
子DisplayObjectのinitializeメソッドを呼び出すようにしてあります。

と、いうことで一番初めのButtonクラス生成直後にwidth、heightの値が0となる件にやっと繋がりました。Flex2のDisplayObject系のクラスでは、処理の無駄を省くため、プロパティ実際のビジュアル部分のレイアウトやサイズ等の計算は次の描画タイミング時まで保留されます。そのため、すぐにwidthやheightの値を取得することができません。

以下、対応策の案としては、

1.Flex2のクラスを使わない
元も子もないですが、使わないというのも一手ですよね。
全部flashパッケージ内から賄い、足りない部分は自分で作る、と。
ボタンくらいだったら、SimpleButtonクラスでも十分なことも多いです。

2.callLaterメソッド
UIComponentクラスで定義されているcallLaterメソッドを使います。
(参考:callLaterメソッドの使用)

callLater() メソッドは、現在の更新ではなく、次の画面更新で実行する処理をキューに格納します。

つまりcallLater(hogeMethod)を用いることで、
コンポーネントが描画される(描画用のレイアウト・サイズ計算処理などが終了した)ときに
hogeMethodが呼ばれるので、widthなどの値を取得することができます。

今回のように初期化時だけであれば、
creationCompleteイベントをハンドルしても良いかもしれませんね。

[as3][lib]Go animation system

Flexからアニメーションをガリガリ作る時の標準は今はTweenerライブラリなんでしょうかね?
新しく開発中っぽいアニメーション用のライブラリを見つけたのでメモ。

Go animation system
(現在 closed betaらしい)
* とても軽量(およそ4K)
* 柔軟な設計で、高い拡張性を持つ。
* Fuseのようになんでもできるというようなものではない。
* ただし。Goを使ってFuseのようなものを作ることはできる。
* Goは特殊な書き方を要求しない。
* Goのエンジンは10から20000ものアニメーションを動かすことができる。
* 物理エンジンや3Dエンジンと一緒に使えるよう設計されている。
* GoのアプローチはCairngormフレームワークにインスパイアされている。

だ、そうです。
「物理エンジンや3Dエンジンと一緒に使えるよう設計されている。」ってのが興味深いですね。

FlashDevelop Beta5

気が付けば出てました。
FlashDevelop Beta5。

FlashDevelopでAIRを開発すべく色々と設定を漁ってきましたが、
ついに正式にサポートされたようです。
新規プロジェクトのActionScript3の項目には、

  • Flex 3 Project
  • AIR Flex 3 Projector
  • AIR Projector
  • というFlex3用のプロジェクト項目がデフォルトで入るようになりました。

    これで、誰でも面倒な設定無しでAIRの開発ができますね。
    ・・・と、言いたいところですが、
    まだ設定を自動で全てやってくれるというところまでは言っていないようです。
    なので、手動で設定しましょう。以下2点を設定すれば普通に使えるはずです。

    まずはコンパイラです。
    「Flex3プロジェクト」や「AIRプロジェクト」といっても、
    コンパイラの切り替えを促すようにはなっていないようなので、
    FlashDevelopの通常のFlexSDKをFlex2SDKにしている場合には、
    Flex3のSDKに設定しなおします。
    これは、メニューの「Project」->「Properties」の設定ダイアログから、
    「Compiler Options」タブを選択し、
    「Custom Path to Flex SDK」の項にFlex3のSDKへのパスを設定しましょう。

    続いては、コード補完です。
    コード補完用のファイルはデフォルトで付いてくるようになったのですが、
    それがなぜかプロジェクトに反映されていません。
    これも、メニューの「Project」->「Properties」の設定ダイアログから、
    「Compiler Options」タブを選択し、
    「Intrinsic Libraries」の項に必要なパスを追加しましょう。
    コード補完用のファイルは、(インストールフォルダ)\FirstRun\Library 以下にあります。
    例えば、AIRのプロジェクトなら、

  • Library\AS3\frameworks\Flex3
  • Library\AS3\frameworks\AIR
  • の二つを追加すれば、
    Flex3のmx系のコード補完と、AIR用のコード補完がきくようになります。

    画像は、先日のミニAIRアプリ(13行アプリ)の設定ダイアログです。
    設定ダイアログ

    ミニAIRアプリ

    英語のBlogとか読みますか?

    英語力がなさ過ぎて、いつもすごく時間がかかります。
    GoogleToolBarがマウスオーバーで英単語の意味をポップアップしてくれるのですが、
    残念ながらあまり的確ではありません・・・。

    新しいタブを開いて、英辞郎を開いて検索して・・・、
    が面倒で面倒で!

    なので、サクッとそれっぽいのを作りましょうー。
    で、コードは以下です。

    < ?xml version="1.0"?>
    < mx :Application xmlns:mx="http://www.adobe.com/2006/mxml">
      < mx :Script>
      < ![CDATA[
        private function translate(word:String):void {
          html.location = "http://eow.alc.co.jp/" + word;
          textinput.text = "";
        }
      ]]>
      < /mx:Script>
      < mx :HTML id="html" width="100%" height="100%" />
      < mx :TextInput id="textinput" width="100%" enter="{translate(textinput.text)}" />
    < /mx:Application>
    

    テキストボックスに文字を入れてエンターキーで、英辞郎のページを開きます。
    ま、マッシュアップ(小)。

    13行。よし!と思ってから数分。
    こういう感じでサクッと作れるのがいいですねー。

    Alt+TABでブラウザとAIRアプリを切り替えつつ、ダバダバ読み進めると。
    ん~、まぁ・・・、さすがに実用にはほど遠いですね。

    [IDE]ActionScript3.0(Flex3・AIR)の開発環境構築(3)

    FlashDevelop3.0.0 Beta4が出ましたね。
    設定の仕方は、こちら
    [IDE]ActionScript3.0(Flex3・AIR)の開発環境構築(1)
    [IDE]ActionScript3.0(Flex3・AIR)の開発環境構築(2)
    に書きましたが、少し設定の方法も変わったようなので、
    FlashDevelop3.0.0 Beta4でFlex/AIR対応させるやり方を新しく書きます。
    (自分用の備忘録に近いですが・・・)

    まず、FlashDevelop3.0.0をインストールをしましょう。
    とりあえずFlashDevelopを起動できるところまでいったら、
    文字コードの設定をします。
    Tools -> Program Settings で、設定ダイアログを開きます。
    左側の項目からMain FlashDevelopを選択し、「その他」の項目の「Default CodePage」
    をUTF8にします。ドロップダウンで選択するだけなので簡単ですが、
    この設定をしないと日本語のコメントなどがかけません。

    続いてFlex3コンパイラの設定をします。
    設定ダイアログの左側の項目から、Plugins AS3Contextを選択し、
    「Flex 2 SDK Location」の項目にFlex3のパスを指定します。
    この指定をするときに結構間違うらしいのですが、mxmlcなどがあるbinフォルダ
    をしていると上手く動きません。その上のbinフォルダを含むフォルダを指定です。

    それから、コード補完用のファイルを設定します。その辺の設定は、
    [IDE]ActionScript3.0(Flex3・AIR)の開発環境構築(1)のままですね。

    そしてここがBeta4のキモです。なんとこのままではコンパイルが上手くいきません。
    Flex3 Beta3ではfcshが日本語対応したためにFlashDevelopで上手く動かなくなっているのだそうです。ちなみにfcshとは、コンパイルの状態をキャッシュして二度目以降のコンパイル速度を上げるものです。Flex3のsdkには同梱されています。
    [ActionScript3]FlashDevelopとFlex 3 SDK beta 2の相性が悪いのを何とかする
    こちらの記事を参考にコンパイラの設定を直します。
    sdkのbinフォルダ内に「jvm.config」というファイルがあるので、このファイルをエディタで開きます。

    # Arguments to VM
    java.args=-Xmx384m -Dsun.io.useCanonCaches=false

    この部分を、

    # Arguments to VM
    java.args=-Xmx384m -Dsun.io.useCanonCaches=false -Duser.language=en

    と追記して保存しておきます。これでfcshが英語で起動するようです。

    とりあえず、ここまででFlashDevelopでコンパイルができるはずです。チェックしてみましょう。

    AIRプロジェクトの設定についてはほとんど、[IDE]ActionScript3.0(Flex3・AIR)の開発環境構築(2)と同じですが、色々バージョンアップして違うところもあるので、また次回書きます。

    ではでは。

    [AS3]デバッグの方法

    こちらの記事[AS3S.ORGさん]でデバッグに便利な環境について書かれていたので。
    流れに乗って。

    1. Debug Player

    これは必須ですね。FlashPlayerのDebug用バージョン。普通のFlashPlayerだとランタイムエラーとか拾ってくれないので。エラーが出ているのに表示されないのでデバッグが余計大変になってしまいます。しかも、普通に動くけど実はエラーが起きているということもあるというのが曲者です。例えば画像の読み込み時のIOErrorとかですね。気がつかないままリリースすると、他の開発者の人に「あーIOErrorをちゃんとハンドルしてないんだー」みたいなことがばれてしまうのは恥ずかしいです。

    ちなみに、いろんなベータ版とか試してるうちにこっそりとFlashPlayerが新しく置き換わることが結構あって、気がつかないうちにDebugPlayerではなくなっている、ということもあります。DebugPlayerの場合はFlash/Flex上で右クリックしたときに「デバッグ」というコマンド(ただしグレーで実行できない)が入るようですよ。

    2. Flash Tracer

    FireFoxのアドオンでtraceの出力をFlreFoxのサイドバーで確認できるというものです。

    すごい趣味の問題なんですけど、サイドバーじゃなかったらなぁ、と。デバッグ用の出力ウインドウはなんか画面下に欲しいんですよね。
    (FireFoxに他のアドオン入れれば下にできるのかもしれないけど、ブックマークの時とかは横にあって欲しいし・・・)

    3. Flash Switcher

    FireFoxでFlashPlayerのバージョンを切り替えるアドオンです。
    便利なんだけど・・・、他のタブでFlashPlayerが起動してると動かないんですよね。僕は結構タブを多めに開いたままにする派なので、なかなか使いづらい・・・。
    FireFoxが常用のブラウザじゃない人には良いかも。

    あとは、最近いたるところで話しにのぼっている、
    ThunderBoltですね。
    FireBugに出力できるというライブラリです。ただの出力か、警告かエラーかなど色々な出力を簡単に実現できるのは良いところですが、ソースコードにデバッグ用のコードが色々残ってしまうのが若干面倒ですね。
    FireBugに出力するだけ、という意味では、
    ExternalInterface.call("console.log", "hogehoge");
    でだせます。自分でうまいことデバッグ用のクラスを書いたほうが後々便利かもしれませんね・・・。

    [AS3]includeとimport

    Shigeru-Nakagaki.comさんの記事にて、ActionScript3.0でのincludeについての解説がありました。

    importについては、普段つかっているものなので、理解はしていたんですが、
    「include」があることすら知りませんでした・・・。

    include

    コンパイル時にソースを丸ごとぶち込みます
    注意点としては複数のファイルで同じファイルをincludeすると
    無駄にSWFが肥大化しますので、個人的にはお勧めしません ^_^;
    オブジェクト指向なんていう形式的なことは
    毛頭言う気はありませんが、それでもFlexでは
    クラス化したほうが良いと思います

    なるほど。
    ってことは、staticな変数とかは、コンフリクトを起こしてしまうんでしょうかね?
    そもそもincludeの使いどころってどういう状況なんだろう?過去のバージョンとの互換とかのために使えるようになってるだけなら良いんですが、どこかに使いどころがあるんでしょうね、多分。そういえばFlexFrameworkのソースの中にincludeがあったような・・・。

    ちゃんとAdobeから出されているリファレンスとか読み込まないとだめだなぁと痛感しますね。

    いつもその場しのぎで検索していくだけでは・・・だめだっ!

    [Flex]ViewStackの画面切り替え

    ViewStackを使って、画面を切り替えるにはindexかidを使うけど、
    Class名を使うという手もあるよ、という記事から。

    Flex cookbook beta
    Selecting a view in a ViewStack just by its Class

    実際に書くとこんな感じです。

    < ?xml version="1.0" encoding="utf-8"?>
    < mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
     < mx:Script>
      < ![CDATA[
       import mx.core.ComponentDescriptor;
       // 切り替えのスイッチになる変数
       [Bindable]
       public var actualView:Class = TitleWindow;
    
       private function getView(viewClass:Class):int{
        // ViewStackの持つ子画面の配列を取得
        var descriptors:Array = views.childDescriptors;
        for(var i:int=0;i
     < mx:ViewStack id="views" selectedIndex="{getView(actualView )}" width="100%" height="100%">
      < mx:TitleWindow title="TitleWindowView" width="80%" height="80%"/>
      < mx:Panel title="PanelView" width="80%" height="80%"/>
     < /mx:ViewStack>
     < mx:HBox width="100%">
      < mx:Button label="TitleWindow" click="actualView=TitleWindow"/>
      < mx:Button label="Panel" click="actualView=Panel"/>
     < /mx:HBox>
    < /mx:Application>
    

    この方法を使うと、ViewStackに積むそれぞれのViewを全部違うクラスにしなくちゃいけないので、結局id使ってちゃんとそれぞれ名前付けておくのが一番良いのかなぁ。という感じですね。
    でもそれなりの規模のものを作っていて、それぞれの画面をきちんとコンポーネント化して作るような場合には結構便利なのかもしれないですね。

    [Flex]ポップアップウインドウの作り方

    ポップアップウインドウとか、たまに必要になるのに、そのたびに作り方忘れるのでメモ。

    まずはポップアップで開くウインドウをコンポーネントとして作ります。

    < ?xml version="1.0" encoding="utf-8"?>
    < mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" showCloseButton="true" close="closePopup()" width="400" height="300">
      < mx:Script>
        < ![CDATA[
          import mx.managers.PopUpManager;
    
          private function closePopup():void{
            PopUpManager.removePopUp(this);
          }
        ]]>
      < /mx:Script>
    < /mx:TitleWindow>
    

    簡単に作るならTitleWindowがいいかな?
    showCloseButtonで閉じるボタンができるので楽チンです。
    closeイベントを取得して、PopupManagerから自分自身を削除するようにすると、ポップアップが消せます。

    そしたらポップアップを開く側を。

    < ?xml version="1.0" encoding="utf-8"?>
    < mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
      < mx:Script>
        < ![CDATA[
          import mx.managers.PopUpManager;
    
          public function doPopup():void{
            var popup_window:PopupWindow = new PopupWindow();
            // PopupManagerにインスタンスを登録
              PopUpManager.addPopUp(popup_window, this);
            // 画面中央へ表示
              PopUpManager.centerPopUp(popup_window);
          }
        ]]>
      < /mx:Script>
      < mx:Button label="Popup" click="doPopup()"/>
    < /mx:Application>
    

    とりあえずサンプルなので、ポップアップを開くためのボタンだけ配置。この辺は適宜ですね。
    addPopUpの引数は、
    第一引数がwindow:IFlexDisplayObject。
    ポップアップさせるインスタンス
    第二引数がparent:DisplayObject。
    ポップアップ表示の親となるDisplayObject。次のcenterPopUpのときの中心座標を計算する基準になるっぽい。
    第三引数がmodal:Boolean = false 。
    trueだと、ポップアップ表示中は、ポップアップ以外が操作不能になります。
    第四引数はchildList:String = null 。
    与えられる引数は以下の三種。
    PopUpManagerChildList.APPLICATION
    PopUpManagerChildList.PARENT
    PopUpManagerChildList.POPUP

    APPLICATIONはSTAGE以下に、PARENTは第二引数のparent以下に、POPUPはSystemManager以下にDisplayObjectを追加します。

    他の方法としては、
    centerPopUp(popUp:IFlexDisplayObject):void
    このメソッドでは、クラスネームを引数で渡します(インスタンスではなく)。

    ん~、リファレンスのPopupManagerの説明が微妙にわかりづらいんですよね。

    [Flex3]Flex3 Beta2

    Flex3のBeta2がやっと出ましたね。
    さっそく入れてみましたが、AIRのSDKもバージョンアップしているようで、
    これから色々試していかなければ・・・。

    Beta1からどこが変更されたのかについては、
    Adobe AIRで作るデスクトップアプリケーション 第10回 Adobe AIR ベータ2公開
    こちらの記事が良くまとまっていてわかりやすいですね。

    アプリケーション記述ファイルの

    <rootContent>要素が削除され,代わりに<initialwindow>要素が追加された。

    って部分には参りました。今までのプロジェクトが全部動かなくなって焦った・・・。

    すごいニッチなことかもしれないけど、Flex3 Beta1では、自己署名証明書のサイトにはアクセスできないようになってたのかな?自己署名なhttpsサイトにアクセスしようとすると、IOErrorが返ってきてしまうバグに悩まされていたんだけど、Flex3 Beta2にしたら普通にアクセスできるようになりました。

    んー、Beta1ではそういう仕様だったのかなぁ・・・?

    Home > Flex3

    Search
    Google
    Feeds
    Meta
    Advertisement

    Return to page top