Flex ActionScript 関連覚書などなど

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
< ?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<descriptors .length;i++){
     // 各子画面のtypeプロパティでクラス名を取得
     // そのクラス名からIndexを得る
     var descriptor:ComponentDescriptor = descriptors[i];
     if(viewClass==descriptor.type) return i;
    }
    // クラス名がどれともマッチしなければエラー
    throw new Error("View of " + viewClass + " not found.");
   }
  ]]>
 < /mx:Script>
 < 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使ってちゃんとそれぞれ名前付けておくのが一番良いのかなぁ。という感じですね。
でもそれなりの規模のものを作っていて、それぞれの画面をきちんとコンポーネント化して作るような場合には結構便利なのかもしれないですね。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
< ?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から自分自身を削除するようにすると、ポップアップが消せます。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
< ?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の説明が微妙にわかりづらいんですよね。

as3でzipの操作用ライブラリ

FZip
ライセンスはzlib/libpng license
商用利用もOKなライセンスっぽい。

zipの解凍用で圧縮はできないのかな?このライブラリは。
.airファイルの中身をのぞいたりもできますね。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
< ?xml version="1.0" encoding="utf-8"?>
< mx :WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
  < mx :Script>
    < ![CDATA[
      import deng.fzip.FZip;
      public var fzip:FZip;
      public function init():void{
        fzip = new FZip();
        var req:URLRequest = new URLRequest();
        req.url = "hogehoge.air";
        fzip.addEventListener(Event.COMPLETE, loadComplete);
        fzip.load(req);
      }
      public function loadComplete(e:Event):void{
        status = fzip.getFileCount().toString();
        for(var i:int=0;i&lt;fzip .getFileCount();i++){
          ta.text += fzip.getFileAt(i).filename+"\n";
          ta.text += fzip.getFileAt(i).getContentAsString();
          ta.text += "\n\n";
        }
      }
    ]]>
  < /mx>
  < mx :TextArea id="ta" width="100%" height="100%"/>
< /mx:WindowedApplication>

[Flex3]Flex3 Beta2

カテゴリー Flex

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

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

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

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

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

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

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

fxug – フォーラム

ここによると、

alert = Alert.show("hogehoge");

で開いたAlertは、

PopUpManager.removePopUp(alert);

で消せるらしいです。

確かにリファレンスを見ると、Alert.show()でAlert型が戻り値になってますね。戻り値あったんだ・・・。この関数。

というかそれ以前にAlertがPopupManagerで開かれていることを知らなかった・・・。
FlexFrameworkのソースって読めるんですよね。やっぱソースとかしっかり読んで勉強するべきなのかなぁ・・・。

前回の続きです。

前回はFlashDevelopのインストールから、Flex3のSDKを適応し、
コード補完をできるようにするところまででした。

今回は、AIRの開発用のProjectTempleteを作ります。

まずは、FlashDevelopをインストールしたフォルダを確認してください。
特に変更せずにインストールしていれば、
(Windowsなら)C:\Program Files\FlashDevelop\だと思います。
そこからさらにもぐって、
C:\Program Files\FlashDevelop\FirstRun\Templates\ProjectTemplates\
を確認します。
[ProjectTemplates]フォルダ内には、
[00 ActionScript 2 - Empty Project]~[08 HaXe - Default Project]までの
プロジェクトテンプレートファイルがあります。
どれでも良いですが、とりあえず[06 ActionScript 3 - Default Project]をコピーして、
[09 Air - Default Project]という名前にリネームします。
これで、Air用の新しいプロジェクトができました。

FlashDevelop再起動後にnew Projectで確認できると思います。

次はAirプロジェクトのコンパイル設定です。
swfをAirアプリにするためには、application descriptor fileというxmlファイルが必要です。
new Projectの際に自動でこのファイルができるように、
[09 Air - Default Project]フォルダ内にapplication.xmlというファイルを作っておきましょう。

< ?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://ns.adobe.com/air/application/1.0.M4" appId="net.jinten.air.hoge" version="0.1">
  <name>hoge</name>
  <title>hoge</title>
  <rootcontent width="480" height="640" systemChrome="standard" transparent="false" visible="true">
    hoge.swf
  </rootcontent>
</application>

これで新規プロジェクトの際には、自動的にapplication.xmlというファイルができることになります。

次にコンパイルのオプションを設定します。
[09 Air - Default Project]フォルダ内の Project.as3proj というファイルをメモ帳で開いてみてください。
中身はXML形式で書かれています。
まず、build という項目に以下を追記します。

<build>
  <option additional="+configname=air" />
       ・
       ・
       ・
</build>

続いて、
postbuildCommand という項目を以下のように修正します。

<postbuildcommand alwaysRun="False">
  "C:\path\to\flex3_sdk\bin\adl.exe" application.xml
</postbuildcommand>

adlへのパスは環境に合わせてください。

これで設定は終了です。
FlashDevelopを再起動し、Airプロジェクトを新規で作ってください。
自動で作られたapplicaiton.xml内のrootContentで指定するswfを適当に調整し、
F8でAirアプリの完成です。

Flex3の開発環境といえば、FlexBuilder3。
ですが、使用期限ももう限界です。

僕は少し前からFlashDevelop3.0に切り替えました。
AIRの開発に他の人は何を使ってるんだろう・・・。
ここを見ながら設定するとAIRの開発に問題無しです。

若干コード補完がおかしいときがありますが、
体感的にはFlexBuilderよりも軽いし、無料だし。

ほぼそのままですが、開発環境の構築手順を。

まずはFlashDevelopをここからダウンロードします。
2007年8月11日現在、最新版はFlashDevelop 3.0.0 Beta2のようです。
そして、インストール。
FlashDevelopの起動には「.NET Framework 3.0」が必要なので、インストール前に入れておきましょう。
インストール後

英語ですが、普通に進めれば問題無くインストールできると思います。
うまくインストールできたら文字コードを設定します。
これをしておかないと、FlexBuilderからのファイルとかを移行したときに日本語が化けます。
メニューから、
Tools -> Program Settings -> その他 -> Default CodePage と選択して、
ここの数値を「1252」から「65001」に変更します。これでUTF-8になるようです(細かいことはわかってない)。
情報元はここ

それでは、ここからはAIRのBeta1とかFlex3用のプロジェクトを作る設定です。

まずはFlex3のSDKを設定します。
先ほどと同様に、Tools -> Program Settings から、
plugins -> AS3Context -> settings
と選択していきます。
すると、「AS3Contexet」というタイトルのウインドウが出るはずなので、
その中の、AS3項目内「Flex 2 SDK Location」にFlex3のSDKを設定します。
(SDKの設定なので、mxmlcのあるフォルダの上のフォルダを設定)

続いてコード補完用のファイルを設定します。
まずは、このページのはじめの書き込みの「Update: Flex 3/AIR Intrinsic Classes 」という部分から「flex3_intrinsic.zip」というファイルをダウンロードしてください。

先ほどの、「AS3Context」ウインドウをもう一度開き、
今度は、「AS3 Classpath」というところを先ほどダウンロードしてきたflex3_intrinsic.zipを解凍したものを設定します。

一度、FlasDevelopを再起動し、
新しいProjectを作ってみましょう。

project -> new Project

で開いたウインドウからProject名などは適当に。Templeteは「ActionScript3 – Default Project」で。
すると、
新しいプロジェクト(AS3 Default)
こんな感じに自動でファイルが作られます。

F8押すか、
Project -> Build Project
で、コンパイルできるはずです。

適当にFlex3で新しく追加されたクラスなどを書いてみてください。
コード補完は Ctl + space です。

コレでFlex3と同様のswfをコンパイルできるようになりました。
が、しかし、AIRの開発を行うためにはもう少し設定を続けなければいけません。

続く。

ActionScriptから外部のリソースをロードするには、

1
2
3
4
var uloader:URLLoader = new URLLoader();
uloader.addEventListener(Event.COMPLETE, completeHandler);
var ureq:URLRequest = new URLRequest("http://www.hogehoge.com/resource.txt");
uloader.load(ureq);

普通こんな感じですね。
それで、

1
2
3
private function completeHandler(e:Event):void{
    var resource_txt:String = e.target.data;
}

こんな感じで受け取ります。
ただしコレだとロードしたデータがキャッシュされてしまいます。

開発の途中でキャッシュのせいで予想した結果が返ってこなくて、
無駄な時間をすごしたことも数知れず。

キャッシュしないようにするためには、

1
2
3
4
5
6
var uloader:URLLoader = new URLLoader();
uloader.addEventListener(Event.COMPLETE, completeHandler);
var header:URLRequestHeader = new URLRequestHeader("pragma", "no-cache");
var ureq:URLRequest = new URLRequest("http://www.hogehoge.com/resource.txt");
ureq.requestHeaders.push(header);
uloader.load(ureq);

こんな感じになります。
URLRequestHeaderでpragma:no-cacheというものを渡してあげます。
すると、ブラウザがキャッシュをしなくなります。

ただしIEの場合、
どうも一度アプリケーションを終了するまではno-cache指定していてもキャッシュしてしまう様子です。
[HOWTO] Internet Explorer でキャッシュを無効にする
ここによると、

Pragma: no-cache は、セキュリティで保護された接続で使用された場合にのみ、キャッシュを実行しません。Pragma: no-cache META タグが、セキュリティで保護されていないページで使用された場合、Expires: -1 とまったく同じ働きをします。そのページはキャッシュされますが、直ちに期限が切れるものとしてマークされます。

だそうです。
つまり、no-cacheでもキャッシュされます。なのでリロードしてもキャッシュから読まれてしまいます。
一度アプリケーションを終了すればキャッシュが消えます。
開発時にIEを使っていて、外部のテキストとかを読み込む場合には要注意ですね。
IE使いづらい!

navigateToURLを使って新しいウインドウを開く場合には、
ブラウザのポップアップブロックに引っかかるときがある。

navigateToURLでは無く、JavaScriptを使ってウインドウを開いてやれば良いらしい。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
< ?xml version="1.0" encoding="utf-8"?>
< mx :Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical">
  <mx :Script>
    < ![CDATA[
      import flash.net.navigateToURL;
 
      private function openNewWindow( event:MouseEvent, url:String, winName:String, w:int, h:int, toolbar:int, location:int, directories:int, status:int, menubar:int, scrollbars:int, resizable:int):void{
        var fullURL:String = "javascript:var myWin;" + "if(!myWin || myWin.closed)" + "{myWin = window.open('" + url + "','" + winName + "','" + "width=" + w + ",height=" + h  + ",toolbar=" + toolbar + ",location=" + location + ",directories=" + directories + ",status=" + status + ",menubar=" + menubar + ",scrollbars=" + scrollbars + ",resizable=" + resizable + ",top='+((screen.height/2)-(" + h/2 + "))+'" + ",left='+((screen.width/2)-(" + w/2 + "))+'" + "')}" + "else{myWin.focus();};void(0);";
        var u:URLRequest = new URLRequest(fullURL);
        navigateToURL(u,"_self");
      }
    ]]>
  </mx>
  <mx :Button label="JavascriptFunction" click="openNewWindow(event, 'http://www.adobe.com/', 'adobe', 800, 600, 1, 1, 1, 1, 1, 1, 1);"/>
  <mx :Button label="navigateURL" click="{navigateToURL(new URLRequest('http://www.adobe.com/'));}" />
< /mx>

メニューバーやツールバーの有無は0,1のフラグで渡す。
FireFoxとOperaとIEでは確かめてみたけど、確かにウインドウが開いた。
設定によると思うけど、FireFoxでは新しいタブとして開いた。

こういう場合を考えると、やっぱりwidthとheightは設定するべきじゃないなぁ。
ブラウザ全体のサイズが調整されてしまう。

[情報元]Adobe Flex cookbook beta

備忘録的にメモ。

Apacheのhttpd.confか.htaccessに、

AddType application/vnd.adobe.air-application-installer-package+zip air

を、加えてやる。

[情報元]Flex Coderさん

« 戻る他のキーワードで検索 »