FlashOOP詳細(4):アプリケーションフレームワーク、XMLデータの読み込み

本日の予定

本日も引き続き、FlashOOPの基本を学んでいきます。

まずはじめに、今後、複数のクラスを複雑に組合せてひとつのアプリケーションを構築していく場合を想定して、より整理されたアプリケーション構築のためのフレームワークの作り方を学んでいきます。クラスファイルの名前やメソッド名の重複などがないように多数のクラスを共存させるためにはどうするのか、ソースファイルとWebサイト側のイメージをどのように一致させていくのか、などについて学びます。

後半は、ActionScript2のXMLオブジェクトを活用して、Flashに読み込むファイルの管理やパラメータの読み込みの方法をサンプルを通して学んでいきます。サンプルとして簡単な画像スライドショーを作成します。これが今後のマッシュアップアプリの基礎となっていくので、順を追ってじっくりと学んでいきましょう。

本日のスライド

サンプルファイル

目次

Flash応用講座(4)

今日の内容

OOPアプリケーションフレームワーク

ディレクトリ構造の標準化

現在のディレクトリ構造

フラッシュ書類(.flaファイル)

フラッシュ書類(.flaファイル)

クラス

クラスファイルの構造的な配置

ディレクトリ構造

FLAファイルからメインのA.asクラスをインスタンス化する

import com.somedomain.A;
A.main();

A.asクラス

import com.somedomain.B;
class com.somedomain.A {
    private static var bInstance:B;
    public function A () {
	// コンストラクタは未使用
    }
    public static function main ():Void {
	trace("Starting application.");
	bInstance = new B();
    }
}

B.asクラス

class com.somedomain.B {
    public function B () {
	trace("クラスBのインスタンス化");
    }
}

XMLデータの活用

XML(Extensible Markup Language)

FlashとXML

XMLを用いたスライドショーを作成してみる

ディレクトリ構造を整理する

画像データの整理

アプリケーションの設計

アプリケーションの設計

クラスの相関図(UMLクラス図)

UMLクラス図

XMLファイルの作成

XMLファイルの構造

XMLファイルの構造

クラス”Slideshow”のインスタンス化

クラスの作成

Slideshowクラス

//GUIコンポーネントのクラスパス
import mx.controls.*;
//Slideshowのクラスパス
import org.yoppa.slideshow.SlideshowXml;
class org.yoppa.slideshow.Slideshow {
    //このオブジェクト
    private var thisSlide:Slideshow;
    //このオブジェクトへのXMLローダーのオブジェクト
    private var thisXml:SlideshowXml;
    //このオブジェクトのターゲットパス
    private var target_mc:MovieClip;
    //XMLより読み込まれるスライドのリスト(URLとスライドの名前)
    private var slideList:Array;
    //現在表示しているスライド番号
    private var currentSlideNum:Number;
    //スライドの写真を貼り付けるムービークリップ
    private var photo_mc:MovieClip;
    //スライドのタイトルを表示するテキストエリア
    private var slideText:TextArea;
    //「前の写真」ボタンと「次の写真」ボタン
    private var prevButton:Button, nextButton:Button;
    //コンストラクタ
    public function Slideshow(target:MovieClip) {
	target_mc = target;
	//現在のスライド番号を初期化
	currentSlideNum = 0;
	//GUI(ボタン、テキストフィールド)の生成
	createGui();
	//XMLファイルを読みこむためのクラスをインスタンス化
	thisXml = new SlideshowXml();
	//XMLファイルを読みこんで、makeSlide関数をコールバック
	thisXml.loadXML("/media/1/xml_slideshow/slides.xml", makeSlide, this);
    }
    //GUIコンポーネントを利用して、インタフェイスを生成
    private function createGui():Void {
	var thisSlide:Slideshow = this;
	slideText = target_mc.createClassObject(mx.controls.TextArea, 
						"slideText", 
						target_mc.getNextHighestDepth());
	slideText.move(10, 120);
	slideText.setSize(144, 24);
	prevButton = target_mc.createClassObject(mx.controls.Button, 
						 "prevButton", 
						 target_mc.getNextHighestDepth(), 
						 {label:"前の写真"});
	prevButton.setSize(70, 24);
	prevButton.enabled = false;
	prevButton.move(10, 150);
	prevButton.clickHandler = function(e:Object):Void  {
	    thisSlide.showPrevSlide();
	};
	nextButton = target_mc.createClassObject(mx.controls.Button, 
						 "nextButton", 
						 target_mc.getNextHighestDepth(), 
						 {label:"次の写真"});
	nextButton.setSize(70, 24);
	nextButton.move(prevButton._x+prevButton.width+5, prevButton._y);
	nextButton.clickHandler = function(e:Object):Void  {
	    thisSlide.showNextSlide();
	};
    }
    //スライドを初期生成
    public function makeSlide(list:Array, target:MovieClip):Void {
	slideList = list;
	photo_mc = target_mc.createEmptyMovieClip("photo_mc", 
						  target_mc.getNextHighestDepth());
	photo_mc._x = 10;
	photo_mc._y = 10;
	viewSlide();
    }
    //番号に合わせた写真とテキストを表示
    private function viewSlide():Void {
	loadMovie(slideList[currentSlideNum].jpegURL, "photo_mc");
	slideText.text = slideList[currentSlideNum].slideText;
    }
    //次のスライドを表示
    private function showNextSlide():Void {
	prevButton.enabled = true;
	currentSlideNum++;
	viewSlide();
	if (currentSlideNum>=slideList.length-1) {
	    nextButton.enabled = false;
	}
    }
    //前のスライドを表示
    private function showPrevSlide():Void {
	nextButton.enabled = true;
	currentSlideNum--;
	viewSlide();
	if (currentSlideNum<=1) {
	    prevButton.enabled = false;
	}
    }
}

SlideshowXmlクラス

import org.yoppa.slideshow.*;
class org.yoppa.slideshow.SlideshowXml {
    private var slidexml:XML;
    //XMLデータを外部ファイルから読み込む
    public function loadXML(url:String, callFunc:Function, callObj:Object):Void {
	//XMLオブジェクトを作る
	var slidexml:XML = new XML();
	//空白行を無視する
	slidexml.ignoreWhite = true;
	//読み込み完了のイベントハンドラ
	slidexml.onLoad = function(success:Boolean) {
	    if (success) {
		// Slideのリスト
		var slideList = new Array();
		// XMLの解析(parse)
		var rootNode = this.firstChild;
		//スライドの数だけ繰り返し
		for (var aNode = rootNode.firstChild; 
		     aNode != null; 
		     aNode=aNode.nextSibling) {
		    var slideObj = new Object();
		    //画像のURLを取得
		    slideObj.jpegURL = aNode.attributes["jpegURL"];
		    //スライドのタイトルを取得
		    slideObj.slideText = aNode.firstChild.nodeValue;
		    //slideListへの追加
		    slideList.push(slideObj);
		}
		//解析完了をコールバックする
		callFunc.call(callObj, slideList);
	    } else {
		//XMLの取得に失敗
		//エラー処理を行う場合はここから呼び出す
	    }
	};
	//(ローカルの)XMLファイルの読み込みを実行する
	slidexml.load(url);
    }
}

最終的なUMLクラス図

最終的なUML図

応用:Livedoor Weather Web Systemを利用してみる

お天気Webサービス(Livedoor Weather Web Service / LWWS)

Livedoorお天気Webサービス

Lwwsクラス

//GUIコンポーネントのクラスパス
import mx.controls.*;
//Slideshowのクラスパス
import org.yoppa.lwws.*;
class org.yoppa.lwws.Lwws {
    //LivedoorWebサービス、XML取得URL
    private var url:String 
	= "http://weather.livedoor.com/forecast/webservice/rest/v1?city=63&day=tomorrow";
    //このオブジェクト
    private var thisLwws:Lwws;
    //このオブジェクトへのXMLローダーのオブジェクト
    private var thisXml;
    //このオブジェクトのターゲットパス
    private var target_mc:MovieClip;
    //GUI要素
    private var titleLabel:Label;
    private var telopLabel:Label;l
    private var temperatureLabel:Label;
    private var descriptionText:TextArea;
    private var icon_mc:MovieClip;
    //コンストラクタ
    public function Lwws(target:MovieClip) {
	target_mc = target;
	//GUI(ボタン、テキストフィールド)の生成
	createGui();
	//XMLファイルを読みこむためのクラスをインスタンス化
	thisXml = new LwwsXml();
	//XMLファイルを読みこんで、makeSlide関数をコールバック
	thisXml.loadXML(url, showWeather, this);
    }
    //GUIコンポーネントを利用して、インタフェイスを生成
    private function createGui():Void {
	//メインタイトル(ラベル)
	titleLabel = target_mc.createClassObject(mx.controls.Label, 
						 "titleLabel",
						 target_mc.getNextHighestDepth());
	titleLabel.setSize(300, 24);
	titleLabel.move(10, 10);
	titleLabel.setStyle("fontSize", 18);
	//お天気アイコン(画像表示用のMovieClip)
	icon_mc = target_mc.createEmptyMovieClip("icon_mc", 
						 target_mc.getNextHighestDepth());
	icon_mc._x = titleLabel._x;
	icon_mc._y = titleLabel._y+titleLabel.height+10;
	//天気名(ラベル)
	telopLabel = target_mc.createClassObject(mx.controls.Label, 
						 "telopLabel", 
						 target_mc.getNextHighestDepth());
	telopLabel.setSize(60, 20);
	telopLabel.move(icon_mc._x, icon_mc._y+32);
	//気温(ラベル)
	temperatureLabel = target_mc.createClassObject(mx.controls.Label, 
						       "temperatureLabel", 
						       target_mc.getNextHighestDepth());
	temperatureLabel.setSize(300, 80);
	temperatureLabel.move(telopLabel._x+telopLabel.width+5, telopLabel._y);
	//気象概況とピンポイント天気(テキストエリア)
	descriptionText = target_mc.createClassObject(mx.controls.TextArea, 
						      "descriptionText", 
						      target_mc.getNextHighestDepth());
	descriptionText.setSize(460, 240);
	descriptionText.move(telopLabel._x, telopLabel._y+telopLabel.height+10);
	descriptionText.html = true;
	descriptionText.wordWrap = true;
	descriptionText.editable = false;
	descriptionText.vScrollPolicy = "on";
    }
    private function showWeather(weatherObj:Object):Void {
	//メインタイトルのテキストを設定
	titleLabel.text = weatherObj.title;
	//天気名のテキストを設定
	telopLabel.text = weatherObj.telop;
	//お天気アイコンの画像をロード
	loadMovie(weatherObj.imageUrl, "icon_mc");
	//最高気温と最低気温をまとめて表示
	temperatureLabel.text 
	    = "最低気温:"
	    +weatherObj.temperatureMin
	    +"℃  最高気温:"+weatherObj.temperatureMax+"℃\n";
	//気象概況を表示
	descriptionText.text 
	    = "気象概況:\n"+weatherObj.description+"\n\n";
	//ピンポイント天気予報の表示
	descriptionText.text 
	    += "ピンポイント天気予報:\n";
	for (var i:Number = 0; i<weatherObj.pinpointTitleList.length; i++) {
	    //ピンポイントの数だけ地域名を表示、ピンポイント予報のリンクを付加
	    descriptionText.text 
		+= "<font color=\"#0000ff\"><a href=\""
		+weatherObj.pinpointUrlList[i]+"\">"
		+weatherObj.pinpointTitleList[i]+"</a></font>";
	}
    }
}

LwwsXmlクラス

// ライブドアお天気Webサービス(REST)XML解析
// お天気Webサービス仕様
// http://weather.livedoor.com/weather_hacks/webservice.html
// ---
class org.yoppa.lwws.LwwsXml {
    private var lwwsXml:XML;
    //XMLデータを外部ファイルから読み込む
    public function loadXML(url:String, callFunc:Function, callObj:Object):Void {
	//XMLオブジェクトを作る
	var lwwsXml:XML = new XML();
	//空白行を無視する
	lwwsXml.ignoreWhite = true;
	//読み込み完了のイベントハンドラ
	lwwsXml.onLoad = function(success:Boolean) {
	    if (success) {
		// 読み込みに成功 → XMLの解析開始
		//コールバック用オブジェクトの初期化
		var weatherObj = new Object();
		//ルートノードの定義
		var rootNode = this.firstChild;
		//ルートノード以下の子ノードが存在する限り解析を続ける
		for (var aNode = rootNode.firstChild; 
		     aNode != null; 
		     aNode=aNode.nextSibling) {
		    //ノードの名前をキーにして、必要な値を抽出し、
		    //オブジェクトweatherObjのプロパティーとして追加する
		    switch (aNode.nodeName) {
		    case "title" :
			//メインタイトル
			weatherObj.title = aNode.firstChild.nodeValue;
		    case "telop" :
			//天気名
			weatherObj.telop = aNode.firstChild.nodeValue;
		    case "description" :
			//気象概況
			weatherObj.description = aNode.firstChild.nodeValue;
		    case "image" :
			//imageノードのさらに下の階層のノードを解析
			for (var aaNode = aNode.firstChild; 
			     aaNode != null; 
			     aaNode=aaNode.nextSibling) {
			    switch (aaNode.nodeName) {
			    case "url" :
				//お天気アイコンの画像ファイルのURL
				weatherObj.imageUrl = aaNode.firstChild.nodeValue;
			    }
			}
		    case "temperature" :
			//temperatureノードのさらに下の階層のノードを解析
			for (var aaNode = aNode.firstChild; 
			     aaNode != null; 
			     aaNode=aaNode.nextSibling) {
			    switch (aaNode.nodeName) {
			    case "max" :
				//最高気温
				weatherObj.temperatureMax 
				    = aaNode.firstChild.firstChild.nodeValue;
			    case "min" :
				//最低気温
				weatherObj.temperatureMin 
				    = aaNode.firstChild.firstChild.nodeValue;
			    }
			}
		    case "pinpoint" :
			//pinpointノードのさらに下の階層のノードを解析
			//ピンポイント天気の地名とURLのリストを準備
		    var pinpointTitleList:Array = new Array();
		    var pinpointUrlList:Array = new Array();
		    //ピンポイント地域の数だけ、リストに追加していく
		    for (var aaNode = aNode.firstChild; 
			 aaNode != null; 
			 aaNode=aaNode.nextSibling) {
			switch (aaNode.firstChild.nodeName) {
			case "title" :
			    //ピンポイント予報、地名(リストに追加)
			    pinpointTitleList.push(aaNode.firstChild.firstChild.nodeValue);
			case "link" :
			    //ピンポイント予報、URL(リストに追加)
			    pinpointUrlList.push(aaNode.childNodes[1].firstChild.nodeValue);
			}
		    }
		    //地名とURLのリストをオブジェクトweatherObjに追加
		    weatherObj.pinpointTitleList = pinpointTitleList;
		    weatherObj.pinpointUrlList = pinpointUrlList;
		    }
		}
		//解析完了後、解析結果weatherObjをコールバックする
		callFunc.call(callObj, weatherObj);
	    } else {
		//XMLの取得に失敗
		//エラー処理を行う場合はここから呼び出す
	    }
	};
	//(ローカルの)XMLファイルの読み込みを実行する
	lwwsXml.load(url);
    }
}

Comments

コメントはありません

Add Comment

このアイテムは閉鎖されました。このアイテムへのコメントの追加、投票はできません。

トップページに戻る