2008年12月22日

ActionScript3.0でのMVC

去年の今時分にActionScript3.0の勉強がてら作っていたMVCモデルのフレームワーク、今改めて見てみると明らかにおかしいというか根本的に間違っているような気がします。

ControllerにXMLリクエストを書くのは違うだろ自分、ControllerはModelに依頼するだけでリクエスト自体はModelに持たせるべき…。

コード自体もなんかおかしい。
というわけでちゃんと今日(昨日)から書き直しています。

と言っても、夏以降ほとんどFlashLite1.1しかやってないし、それ以前はFlex/Cairngormばかり触っていたので、FlashCS3/ActionScript3.0の書き方から思い出さないといけません。

さっそく、getDefinitionByName()の使い方でハマる。
絶対前にも同じところでハマってるはずなのに、忘れてるんですよね。

カスタムクラスを使うときはフルパスで指定、です。
【日記の最新記事】
posted by imagenos at 00:34| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2008年12月20日

約1年ぶりの更新…

気が付けば前回の更新よりほぼ1年経ってました。
歳取ると時間が流れるのがおっそろしいほど早いですね。


2008年は FlexBuilder3+Cairngorm による開発と、
FlashLite1.1 での携帯コンテンツを割とみっちりやりました。

Flexはいろいろ出来そうなのに、いざやってみると肝心なところが不可能だったり資料がなかったりで苦労しました。
Cairngorm も便利なんだか…。
例によって何度もハマったので、そのあたりを今後ここにフィードバックしていきたいと思います。


逆に FlashLite1.1 はコードの書き方やJava/PHP等との連携によって想像以上にいろんなことが出来るということが解りました。
1つのSWFファイルであらゆる画面サイズの携帯端末にジャストフィットさせる方法があるというのは正直目からウロコでした。
あらかじめいくつかのサイズのSWFを設置しておく、なんて小ざかしいことをしなくても良いというのはかなり素敵です(ちょっと大掛かりですが)。


あとは ActionScript2.0 によるMVCフレームワークを散発的にいじりました。
こう考えてみると、Flex/AS3、AS2、FlashLite1.1と、Flashと一口に言ってもそれぞれが全然互換性がないので、
どれかを長い期間触ってると他のものを忘れてしまいます。

とりあえず年末年始の時間を利用して、復習もかねてこのブログにメモしておきたいと思います。
posted by imagenos at 17:28| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2008年01月23日

XMLをロード

Flashコンテンツに無くてはならないXMLのロード部分を作ってみようと思います。

イメージとしては、フレームワーク内のどこからでもリクエストが可能で、読み込んだXMLデータはModel内のクラスに作った配列に格納します。そして、格納済みのXMLもどこからでも呼び出して何度でも使えるようにしたいと思います。

まず、XMLロード側から書いてみます。XMLロードは恐らくController経由で行うことになると思うので、AllControllerを経由して、RequestXML.asというクラスにロードするXMLのURLとキー(後述)、文字コードを判定するBooleanを渡しています。さらにそこからLoadXML.asというクラスに渡して、実際のロード処理を行っています(このクラスは大重美幸さん著「Flash ActionScript3.0入門ノート」にあったものを元に、必要な部分を書き直しています)。


LoadXML.as:

package framework.controller{

import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.system.System;
import flash.events.Event;

public class LoadXML{

//////////////////////////////////////////////////////////////////////////////////////

private var o_xmlLoader:URLLoader;
private var o_xml:XML;
private var v_key:String;

//////////////////////////////////////////////////////////////////////////////////////

//Constructor
public function LoadXML(thisUrl:String, thisKey:String, thisCode:Boolean){
trace("LoadXML");
//URLLoader作成
o_xmlLoader = new URLLoader();
o_xmlLoader.dataFormat = URLLoaderDataFormat.TEXT;
o_xmlLoader.addEventListener(Event.COMPLETE, onXMLloaded);

v_key = thisKey;

//URL
var myUrlReq:URLRequest = new URLRequest(thisUrl);

//Unicode以外ならばtrue
System.useCodePage = ! thisCode;

//読み込み開始
o_xmlLoader.load(myUrlReq);
}

//////////////////////////////////////////////////////////////////////////////////////

//読み込み完了
private function onXMLloaded(event:Event):void{
trace("onXMLloaded");
try{

//XMLオブジェクトに変換
o_xml = new XML(o_xmlLoader.data);

//XMLをModelに保存する
Framework.c_allModel.f_saveXML(o_xml, v_key);

o_xmlLoader = null;
o_xml = null;

}catch(err:TypeError){
trace(err.message);
}
}

//////////////////////////////////////////////////////////////////////////////////////

}
}


ここで追加・変更している点は、ロードしたXMLをModel内に格納するときに使用するユニークキーの存在と、ロード完了した後にイベントで通知を返すのではなくModelにXMLデータとキーを渡すようにしています。Modelに渡されたXMLデータはAllModelを経由してDataXML.asというクラス内のメンバである連想配列に以下のような感じで格納されます。


DataXML.as内のXML格納部分:

//データを保存し、 Controller に連絡する
public function f_saveXML(thisXML:XML, thisKey:String):void{
trace("DataXML f_saveXML");
xmlArray[thisKey] = thisXML;
Framework.c_allController.f_onLoadXML(thisKey);
}


XMLのロードが完了し、Modelに格納できたらその直後にController経由で再度RequestXML.asにキーを渡しています。このキーによって、次の処理を振り分けるようにswitch文を書いています。前後しましたが以下がそのRequestXML.asです。


RequestXML.as:

package framework.controller{

import flash.events.Event;
import flash.display.DisplayObjectContainer;
import framework.controller.LoadXML;

public class RequestXML{

//////////////////////////////////////////////////////////////////////////////////////

private var c_loadXml:LoadXML;
private var thisXML:XML;

//////////////////////////////////////////////////////////////////////////////////////

//Construnctor
public function RequestXML(){
trace("RequestXML");
}

//////////////////////////////////////////////////////////////////////////////////////

//XMLをリクエストして取得
public function f_requestXML(thisUrl:String, thisKey:String, thisCode:Boolean):void{
c_loadXml = new LoadXML(thisUrl, thisKey, thisCode);
}

//XML取得完了後の処理を分岐
public function f_onLoadXML(thisKey:String):void{

var myXML:XML;

switch(thisKey){
case "aaa":
//処理
break;
case "bbb":
//処理
break;
default:
//処理
break;
}

trace(myXML);

}

//////////////////////////////////////////////////////////////////////////////////////

}
}


RequestXML.asとLoadXML.asは分ける必要はないかもしれませんが、見通しがよくなるように別にしました。

最後に、XMLをロードするコードと、ロードしたXMLを取得するコードです。
Framework経由でアクセスするので、以下の書き方でどこからでも呼べるはずです。



//XMLを読み込み
Framework.c_allController.f_requestXML([ URL ], [ Key ], [ Boolean ]);

//読み込んだXMLを取得
Framework.c_allController.f_onLoadXML([ Key ]);


とりあえず、これでXMLデータが扱えるようになりました。

リクエスト時のURLは静的XMLのものである必要はなく返されるデータ型がXMLであればいいので、PHPやCGIなどに引数付きのURLを渡してDBからデータをセレクト・生成したXMLを返すようにすれば、もっと便利に使えるようになります(まぁ当たり前の事ですけど)。

posted by imagenos at 16:46| Comment(0) | TrackBack(0) | ActionScript 3.0 | このブログの読者になる | 更新情報をチェックする

2007年12月30日

Flash Tracer の導入メモ

MVCの開発とは関係ありませんが、Firefoxの便利なアドオン「Flash Tracer」の導入メモを書いておきます。
インストールの順番を間違えると動かなかった経験があるので、忘れないうちに記録しておきます。


1:Flash Debug Playerのインストール

Flash Tracerを動かすのに必要なFlash Debug Playerをインストールします。
まず、以下のアドレスにアクセスして、既に入ってるかどうかチェックします。
FlashCS3とかと一緒にインストールされるのか、いつの間にかDebug Playerになってたりします。

http://www.adobe.com/jp/devnet/flex/articles/client_debug_02.html

表示されるパラメータが「isDebugger:true 」となってればインストール済みです。
インストールされてなければ、以下からダウンロード。

http://www.adobe.com/support/flashplayer/downloads.html

Flash TracerはFirefoxのアドオンなので「for Netscape-compatible browsers」というやつを入れればOKだと思います。
IEのほうもついでに入れてもいいかもしれません。
この時に普通のFlash PlayerをアンインストールしてからDebug Playerをインストールしたほうがいいみたいです。


2:Flash Tracerのインストール
Firefox2にFlash Tracerを入れます。

https://addons.mozilla.org/ja/firefox/addon/3469

正常にインストールできれば、これでOKなはずです。
どこかTraceが表示される適当なサイトのFlashでも見てみましょう。

http://gazo.clipon.tv/?mode=disp&key=e0iNeMpf6M35


当然ですが、Debug Playerをインストールする前にFlash Tracerを入れてもTraceは表示されません。
なので、一回Flash Tracerを捨ててDebug Playerをインストール、再度Flash Tracerを入れる…という事をすると思いますが、これでも動かないことがあるようです。

詳しいことはよく解りませんが、Flash Tracerを捨ててもその設定ファイルは残ったままになるようで、それも捨てないとダメなようです。
設定ファイルのありかはWinXPの場合「C:\Documents and Settings\[user]\mm.cfg」です。
Debug Playerより先にFlash Tracerを入れてしまってmm.cfgが作られている場合、このファイルも一度破棄してからDebug Playerを入れるとちゃんと動くようです(僕の経験上ですが)。


ちなみに、Flash Tracer導入済みのFirefoxを起動した状態でTraceが出力されるサイトをIEで見ると、なぜかFirefox側でTraceを表示してくれます。
恐らくIE側にもDebug Playerが入ってないとダメだと思いますが、なんか不思議です。
posted by imagenos at 23:45| Comment(0) | TrackBack(0) | ActionScript 3.0 | このブログの読者になる | 更新情報をチェックする

2007年12月18日

カスタムイベントを作ってみる

自分で必要なイベントを作って、好きなときにそれを実行できたらとても便利です。MVCの基本部分を作るついでに、カスタムイベントも使えるようにしてみたいと思います。例によって、やってることが正しいかどうか全然わかりませんが、とりあえず動くようにしてみます。


CustomEvent.as:

package framework.utils{

import flash.events.EventDispatcher;
import flash.events.Event;

public class CustomEvent extends EventDispatcher{

//カスタムイベントを作る
public static const TEST_EVENT:String = "test_event";

//Construnctor
public function CustomEvent(){
trace("CustomEvent");
}

//カスタムイベントTEST_EVENTを払い出すメソッド
public function f_dispatchTestEvent():void{
trace("f_dispatchTestEvent");
dispatchEvent(new Event(TEST_EVENT));
}

}
}


EventDispatcherをスーパークラスとするCustomEvent.asというクラスを作ってみました。これを、framework以下に保存するわけですが、MVCのどれにも属さないような気がするので、framework/utilsというフォルダを新たに作ってそこに置きます。今後utilsにはMVC以外の便利クラスを格納していく予定です。

次に、上記CustomEventのインスタンスをドキュメントクラスのクラスメンバーに格納します。


Framework.asに追加:

package {

import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;
import framework.model.AllModel;
import framework.view.AllView;
import framework.controller.AllController;
import framework.utils.CustomEvent; // 新たにimportする

//ドキュメントクラス
public class Framework extends MovieClip{

//MVCそれぞれのAll*のインスタンスをクラスメンバーに追加
public static var c_allModel:AllModel = new AllModel();
public static var c_allView:AllView = new AllView();
public static var c_allController:AllController = new AllController();
public static var c_customEvent:CustomEvent = new CustomEvent(); // クラスメンバーにインスタンス追加

/**** 中略 ****/

}
}


今度は、カスタムイベントが実行された時に通知を受けたいクラス側でリスナーを登録します。そこで必要なのは以下の3つの要素です。


カスタムイベントを受ける側:

//CustomEventクラスをimport
import framework.utils.CustomEvent;

//ドキュメントクラスのCustomEventインスタンスにリスナー登録
Framework.c_customEvent.addEventListener(CustomEvent.TEST_EVENT, f_eventTest);

//イベントが実行されたときに発動するメソッド
public function f_eventTest(event:Event):void{
trace("function f_eventTest");
}


そして、どこのクラスからでもいいので、カスタムイベントを実行したいタイミングで以下のメソッドを実行します。


カスタムイベントを実行する側:
Framework.c_customEvent.f_dispatchTestEvent();



これでカスタムイベントが発動して、リスナー登録しているクラスに対して通知が行き、それぞれのメソッドが実行される…という感じでしょうか。複数のクラスからリスナー登録してテストしてところ、予期したとおりの動作をしてくれましたが、果たしていいのかどうか…。

作る前にイメージしていたロジックとは微妙に違うので、ちょっと不安ではあります。
posted by imagenos at 01:23| Comment(0) | TrackBack(0) | ActionScript 3.0 | このブログの読者になる | 更新情報をチェックする

2007年12月17日

MVCの基本設計:その1

ドキュメントクラスのクラスメンバーであれば、表示リストに追加されていなくてもFramework.*という感じでどこからでもアクセスできるということが解りました(今のところは、ですが)。

これを利用して、MVCの基本となる部分を構築していきたいと思います。とりあえず、flaファイルとドキュメントクラスであるFramework.asと同じ階層にframeworkというフォルダを作り、さらにその中にmodel,view,controllerというフォルダを作ります。MVCそれぞれの機能を持ったクラス群はこれらのフォルダに分けて設置していく予定です。

さらに、各フォルダ内に1つクラスを作っておきます。構成としては以下のようになると思います。


example.fla
Framework.as
framework/model/AllModel.as
framework/view/AllView.as
framework/controller/AllController.as


MVC各フォルダ内に作るAll*.asというクラスは、これからどんどん増えていくであろう各フォルダ内のクラスへのリファレンス的な役割をさせようと思ってます。基本的に、このAll*.asにアクセスが出来れば、その階層にある全てのクラスへアクセスができるようになれば便利ではないかと考えています。そういうわけで、3つのAll*.asのインスタンスをドキュメントクラスのクラスメンバーに作ってみます。


Framework.asに追加:

package {

import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;

//MVCそれぞれのクラスをインポート
import framework.model.AllModel;
import framework.view.AllView;
import framework.controller.AllController;

//ドキュメントクラス
public class Framework extends MovieClip{

//MVCそれぞれのAll*のインスタンスをクラスメンバーに追加
public static var c_allModel:AllModel = new AllModel();
public static var c_allView:AllView = new AllView();
public static var c_allController:AllController = new AllController();

/**** 中略 ****/

}
}


こんな感じにしておけば、例えばModel内に作ったDataXML.asというクラスのf_getXML()というメソッドにアクセスする場合、AllModel.asがそのクラスへの参照を持っていれば、どこからでもFramework.c_allModel.f_getXML()という感じで呼び出すことができる…はず。このあたりは、今後開発を進めながら考えていきたいと思います。
posted by imagenos at 00:00| Comment(0) | TrackBack(0) | ActionScript 3.0 | このブログの読者になる | 更新情報をチェックする

2007年12月15日

ドキュメントクラスへのアクセス:その2

とりあえずドキュメントクラスを作って、それを他のクラスからアクセスできるようにした訳ですが、ここでひとつ落とし穴?があります。その1で作ったクラスTestMCのコンストラクタ内のaddChild()をコメントアウトすると、rootへの参照がエラーになります。


TestMCのコンストラクタ内を編集:

//Constructor
public function TestMC(thisContainer:DisplayObjectContainer){
//thisContainer.addChild(this); <- コメントアウト
var myRoot = this.root as MovieClip;
myRoot.f_hoge();
}


これは、[Object Framework]([Object MainTimeline]でも同じ)にrootを使用してアクセスする場合、root以下のツリー構造に入っているいずれかの表示オブジェクトの表示リストに追加されている必要があるため…らしいです。とにかく、どこかの表示リストにaddChild()してやらない限り、rootを参照しても「そんなもんねぇーよ」と怒られます。これから作ろうとしているフレームワークのクラス群は、View以外は基本的に表示リストに追加されないはずなので、これでは困ってしまいます。

ただ、上記TestMCの場合、インスタンスを作るときにドキュメントクラスFrameworkからthisを渡してコンストラクタの引数thisContainerで受けているので、それを使用して参照することは可能みたいです。


TestMCのコンストラクタ内を編集:

//Constructor
public function TestMC(thisContainer:DisplayObjectContainer){
//thisContainer.addChild(this);
var myRoot = thisContainer as MovieClip; // thisContainerを型キャストする
myRoot.f_hoge();
}


これでaddChild()後のthis.rootと同じように「ほげほげ」が表示されます。カスタムクラスのインスタンスを作るときに、コンストラクタにrootを渡して、それをそのクラスのメンバーに追加しておけば、表示リストに追加されていないクラスからもFrameworkのプロパティやメソッドを好きなときに使うことができるようです。

もうひとつのやり方は、Framework内のメソッドやプロパティをすべてstaticをつけてクラスメンバーにしてしまう方法です。Framework内のf_hoge()をクラスメンバーにすると、TestMCからはFramework.f_hoge()という感じで実行できます。


Framework内のf_hoge()をクラスメンバーにする:

public static function f_hoge():void{
trace("ほげほげ");
}


TestMCのコンストラクタ内を編集:

//Constructor
public function TestMC(){
Framework.f_hoge(); // クラスメンバーf_hoge()を実行
}


これだと、インスタンスを作るときに毎回rootを渡さなくていいし、受けたほうもメンバーへの追加や型キャストなんかをしなくて良いので、このほうが簡単かもしれません(こういうやり方が正しいのかどうが解りませんが…)。

rootへの参照も、クラスメンバーに追加しておけば好きなときに使えるようにできるようです。Frameworkのコンストラクタで以下のようにクラスプロパティに追加しておいて、getterを作っておけば便利です。


Frameworkを編集:

//クラスプロパティを作る
public static var myRoot:DisplayObjectContainer;

//Constructor
public function Framework(){
trace("Hello,World!!");
myRoot = this; // クラスプロパティにroot自身を代入
var myTestMC:TestMC = new TestMC();
}

//getter
public static function get get_myRoot():DisplayObjectContainer{
return myRoot;
}


TestMCからrootを取りに行く:

//Constructor
public function TestMC(){
trace(Framework.get_myRoot); // [Object Framework]と出力される
}


こんな感じで、表示リストに追加されてないインスタンスからもrootの参照ができるっぽいです。
posted by imagenos at 21:04| Comment(0) | TrackBack(0) | ActionScript 3.0 | このブログの読者になる | 更新情報をチェックする

ドキュメントクラスへのアクセス:その1

とにかくドキュメントクラスを作ってみます。

名前はテキトーに「Framework.as」とつけて、Flaファイルと同じディレクトリに保存します。そして、Flaファイル側でドキュメントクラスを設定します。以下のようなスクリプトであれば、パブリッシュ時にTrace文が表示されるはずです。


Framework.as:

package {

import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;

public class Framework extends MovieClip{

//Constructor
public function Framework(){
trace("Hello,World!!");
}

}
}


ちなみに、Flaファイルのドキュメントクラス設定で入力するのは「クラス名」であって「ファイル名」ではありません(ちょっとハマってしまいました)。ファイル名「Framework.as」で、Flaファイルと同じ階層であれば「Framework」です(当たり前)。

この段階で、rootである[Object MainTimeline]は[Object Framework]と表示されます。表示リストに追加されているオブジェクトから trace(this.root);を実行すると解ります。試しにFramework.asのコンストラクタから、Flaファイルのライブラリ内に作ったMovieClip「TestMC」のインスタンスを生成し、表示リストに追加してからtrace(this.root);を実行してみます。事前にTestMCをリンケージ設定し、「TestMC.as」をFramework.asと同じ階層に保存しておきます。スクリプトはこんな感じでしょうか…?


Framework.as のコンストラクタに追記:

//Constructor
public function Framework(){
trace("Hello,World!!");
var myTestMC:TestMC = new TestMC(this); // TestMCインスタンスを作る
}


TestMC.as:

package {

import flash.display.DisplayObjectContainer;
import flash.display.MovieClip;

//TestMC
public class TestMC extends MovieClip{

//Constructor
public function TestMC(thisContainer:DisplayObjectContainer){
thisContainer.addChild(this);
trace(this.root);
}

}
}


こんな感じでFrameworkにアクセスできるので、Framework内のプロパティやメソッドも外から実行できるはず…。Frameworkに以下のメソッドを追加して、それをTestMCから実行してみます。


Frameworkに以下を追加:

public function f_hoge():void{
trace("ほげほげ");
}


これをTestMCのコンストラクタからthis.root.f_hoge();という感じで呼びます。するとコンパイルエラー「未定義である可能性のメソッドf_hogeをなんたらかんたら…」と怒られてしまいました。これは多分、this.rootで参照するとデータ型がDisplayObjectContainerになっているからメソッドは実行できんよ!という事だと思います。なので、いっかい型をMovieClipにキャストしてから再度やってみます。


TestMCのコンストラクタ内を編集:

//Constructor
public function TestMC(thisContainer:DisplayObjectContainer){
thisContainer.addChild(this);
var myRoot = this.root as MovieClip; // 型キャスト
myRoot.f_hoge();
}


今度は怒られずに「ほげほげ」と出力してくれました。
こんな感じでrootで参照できる共通のメソッドを作っておくと色々便利になるのではと思ってます。
posted by imagenos at 16:29| Comment(0) | TrackBack(0) | ActionScript 3.0 | このブログの読者になる | 更新情報をチェックする

2007年12月14日

ドキュメントクラス

Flash8/ActionScript2.0の頃はフツーにフレームアクションを書いていましたが、ActionScript3.0となった今、スクリプトは全て外部ファイル化したいと考えています。それの良し悪しは別にして、そのほうがよりツウっぽいというか、カッコいいのでそのようなスタイルで行きたいと思います。基本的には、Flashファイル内のフレームにはstop();すら書かないつもりです(可能な範囲で、ですが)。

そうなると、まずどうしても必要となるのが「ドキュメントクラス」です。ドキュメントクラスとは、SWFファイルがロードされたときにトップレベルのDisplayObjectContainerであるStageに対して自動的に生成される[Object MainTimeline](いわゆるroot)にリンケージされるカスタムクラス…ということですが、要はSWFがロードされたら、いの一番に読み込まれるカスタムクラスということだと思います。

このドキュメントクラスを、これから作っていくフレームワークのトップレベルのクラスということにすればいいのかなーと思っています。
posted by imagenos at 23:04| Comment(0) | TrackBack(0) | ActionScript 3.0 | このブログの読者になる | 更新情報をチェックする

ActionScript3.0でMVC

プログラマーではないので細かいところは正直よく解らないのですが、再利用していけるActionScript3.0のフレームワークを作ってみたいと思います。

で、その設計方法ですが、PHPやAS2.0で多少経験のあるMVCでいきたいと思います。ViewとControllerの切り分けがイマイチよくわかりませんが、とりあえず以下のような感じにします。


Model:
ユーザーの入力したデータや外部から取得したXMLなどを保持する。それらの計算ロジックなんかもここに持たせる。

View:
表示リストに入っているMovieClipやSpriteの操作。基本的にUIの出力全般を担当する。また、ライブラリ内のMovieClipにリンケージするクラスもここに格納する。

Controller:
ユーザーがUI経由で何らかのデータを入力したときや、Viewだけで収まらない大きなイベント(SWF内でのページ遷移など?)が発生したときに動作し、内容に応じてModel,Viewに通知する。外部のPHPやCGIとの通信もここから行う。


…こんな感じでしょうか。
うーん、よくわからん。

とはいえ、何のアテもなく作っていけないので、とりえずこの方向で進めたいと思います。
posted by imagenos at 03:59| Comment(0) | TrackBack(0) | ActionScript 3.0 | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。