HAKUHIN's home page
更新履歴
 
 

 

イベントディスパッチャーとは?
 


■ EventDispatcher とは?

ActionScript では、 マウスを動かしたり、マウスをクリックしたり、キーボードを押したりといった操作などさまざまな動作タイミングが、イベントとして定義されています。
 
任意のイベントに対して、事前に好きな関数を登録しておくと、実際にイベントが発生したときに Flash Player からその関数を呼び出してくれます。
 
■ EventDispatcher クラスの派生について
 
EventDispatcher クラスは以下のクラスから派生しています。
 
Object
↓派生
EventDispatcher
 
関連のあるクラス(主なクラスを抜粋)
Stage , MovieClip , Sprite , TextField , Bitmap , Video , Loader , Shape , MainTimeline
 


 

関数を登録してイベントの通知を受け取る
 


■関数を登録してイベントの通知を受け取る

あるイベントが発生したときに実行してほしい関数があるとします。
 
その関数を任意のイベントに登録するには、 addEventListener メソッドを使用します。
 
EventDispatcher.addEventListener ("イベントの種類" , 関数 , キャプチャーを使用するか , 優先度 , 参照レベル );
第01引数 イベントの種類
第02引数 実行される関数
第03引数(略可)true = キャプチャー段階で実行、false = ターゲット,バブリング段階で実行
第04引数(略可)優先度 (0 ~ ) 大きいほど先に実行される
第05引数(略可)参照レベル (true = 弱い 、false = 強い)
戻り値 なし
 
■第01引数 イベントの種類

イベントの種類を指定します。
 
使用するクラスによって、さまざまなイベントが定数として定義されているので、その中から好きなイベントを選択します。
 
■第02引数 実行される関数

イベントが発生したときに実行してほしい関数を指定します。
 
関数には、第01引数に Event 型のオブジェクトを持つ関数を用意します。
 
イベントに登録するコールバック関数を用意する

function TestFunc(e:Event):void{
}
 
実際に呼び出された際に、第01引数からイベントオブジェクトが得られます。
 
Event オブジェクトの currentTarget プロパティから、イベントを登録した自身のインスタンスを取得できます。 target プロパティから、イベントの対象インスタンスを取得できます。
 
毎サイクル実行する

addEventListener(Event.ENTER_FRAME,EnterFrameFunc);
function EnterFrameFunc(event : Event){
	trace("登録:" + event.currentTarget);
	trace("対象:" + event.target);
}

クリックされたか調べる

addEventListener(MouseEvent.CLICK,MouseClickFunc);
function MouseClickFunc(event : MouseEvent){
	trace("登録:" + event.currentTarget);
	trace("対象:" + event.target);
}
 
■第03引数 キャプチャ段階で実行するか

デフォルトでは false です。
 
true にするとキャプチャ段階で実行されます。false にするとターゲット、バブリング段階で実行されます。
 
どちらも実行したい場合は、addEventListener メソッドをもう一度呼び出して第03引数を変更して2回登録します。
 
キャプチャ段階:Stage から子に向かって順番に処理をしていくとき
ターゲット段階:ターゲットとなる対象の処理をするとき
バブリング段階:子から Stage に向かって順番に処理をしていくとき
 
■第04引数 優先度

関数が実行される順番を 0 以上の数値で指定します。数値が高いほど先に実行されます。同じ数値がすでに登録済みの場合、後に登録したほうが優先度が高くなります。

一度登録された関数の優先度を変更する場合は removeEventListener() メソッドで登録を外してから再登録します。
 
優先度が影響するのは、同一のインスタンス内とイベントです。別インスタンス同士の優先度は影響がありません。
 
同一インスタンスであれば関数実行順序を変更できる


var param = [
	{ prio:4 , name : "obj_a" },
	{ prio:0 , name : "obj_b" },
	{ prio:2 , name : "obj_c" },
	{ prio:5 , name : "obj_d" },
	{ prio:1 , name : "obj_e" },
	{ prio:3 , name : "obj_f" },
	{ prio:6 , name : "obj_g" },
];

var sprite = new Sprite();

var i;
for(i=0;i < param.length;i++){
	SpriteSetPraram(i);
}
function SpriteSetPraram(id){
	var prio = param[id].prio;
	var name = param[id].name;
	var count = 0;

	sprite.addEventListener(Event.ENTER_FRAME,function(e){
		trace("name:" + name + " prio:" + prio + " count:" + count);
		count ++;
	},false,prio,prio);
}
 
別インスタンスであれば優先度は影響しない

var param = [
	{ prio:4 , name : "obj_a" },
	{ prio:0 , name : "obj_b" },
	{ prio:2 , name : "obj_c" },
	{ prio:5 , name : "obj_d" },
	{ prio:1 , name : "obj_e" },
	{ prio:3 , name : "obj_f" },
	{ prio:6 , name : "obj_g" },
];

var i;
for(i=0;i < param.length;i++){
	CreateSprite(i);
}

function CreateSprite(id){
	var prio = param[id].prio;
	var name = param[id].name;
	var count = 0;

	var sprite = new Sprite();
	sprite.addEventListener(Event.ENTER_FRAME,function(e){
		trace("name:" + name + " prio:" + prio + " count:" + count);
		count ++;
	},false,prio,prio);
}
 
■第05引数 弱参照レベルを使用するか

デフォルトは false です。

false は、強参照となりガベージコレクションの対象になりません。
 
true に設定すると弱参照となりガベージコレクションの対象になります。 他に参照されていない関数を使ってイベントを登録すると、ガベージコレクションが発生したタイミングでイベントが解放されるようです。
 
System.totalMemory プロパティを使用すると FlashPlayer が使用するメモリ使用量を取得できます。 System.gc() メソッドを使用すると ガベージコレクションを動作させることができます。(デバッグ版Playerのみ動作)
 
■その他

イベントを登録してから再度、まったく同一のパラメータでイベントを登録した場合、二重に登録されることはありません。
 
しかし無名関数を直接渡してイベントを登録すると、関数が新規に作られ別の関数として判別されるので、二重にイベントが登録されます。 タイムライン上で撒き戻し操作などにより、再びイベント登録処理が実行される場合に注意が必要です。
 
インスタンスが「表示リストから外れていて」、「だれからも参照されなくなった」場合、イベントを登録したままでもガベージコレクション が発生するとインスタンスが破棄されるようです。
 



■呼ばれているイベントの段階を調べる

イベントがどの段階で呼ばれているのか調べるには、eventPhase プロパティを使用します。 フェーズの一覧です。
 
定数数値段階
EventPhase.CAPTURING_PHASE1キャプチャ段階
EventPhase.AT_TARGET2ターゲット段階
EventPhase.BUBBLING_PHASE3バブリング段階
 
取得例です。
 
イベントの段階を調べる

// フェーズを日本語で取得
function EventPheaseGetMessage(type:uint){
	switch(type){
	case EventPhase.CAPTURING_PHASE:
		return "キャプチャ段階";
	case EventPhase.AT_TARGET:
		return "ターゲット段階";
	case EventPhase.BUBBLING_PHASE:
		return "バブリング段階";
	}
}

// ムービークリップ配置
var mc:MovieClip = new MovieClip();
mc.graphics.beginFill(0xFF0000);
mc.graphics.drawRect(10,10,100,100);
mc.graphics.endFill();
addChild(mc);

// 毎フレーム呼び出されるイベント
stage.addEventListener(Event.ENTER_FRAME ,function (event:Event):void{
	trace("[Stage] Event.ENTER_FRAME:" + EventPheaseGetMessage(event.eventPhase));
	stage.removeEventListener(Event.ENTER_FRAME ,arguments.callee);
});


// スプライト配置
var sprite:Sprite = new Sprite();

// 子が表示リストが外れたときに呼び出されるイベント
mc.addEventListener(Event.REMOVED,function (e:Event):void{
	trace("[MovieClip] Event.REMOVED:" + EventPheaseGetMessage(e.eventPhase));
},true);
mc.addEventListener(Event.REMOVED,function (e:Event):void{
	trace("[MovieClip] Event.REMOVED:" + EventPheaseGetMessage(e.eventPhase));
});
// 自分が表示リストから外れたときに呼び出されるイベント
sprite.addEventListener(Event.REMOVED_FROM_STAGE,function (e:Event):void{
	trace("[Sprite] Event.REMOVED_FROM_STAGE:" + EventPheaseGetMessage(e.eventPhase));
});

// 表示リストに登録して外す
mc.addChild(sprite);
mc.removeChild(sprite);




// マウスが押されたときに呼び出されるイベント
stage.addEventListener(MouseEvent.MOUSE_DOWN,function (e:MouseEvent):void{
	trace("[Stage] MouseEvent.MOUSE_DOWN:" + EventPheaseGetMessage(e.eventPhase));
},true);
mc.addEventListener(MouseEvent.MOUSE_DOWN,function (e:MouseEvent):void{
	trace("[MovieClip] MouseEvent.MOUSE_DOWN:" + EventPheaseGetMessage(e.eventPhase));
});
stage.addEventListener(MouseEvent.MOUSE_DOWN,function (e:MouseEvent):void{
	trace("[Stage] MouseEvent.MOUSE_DOWN:" + EventPheaseGetMessage(e.eventPhase));
});
 
■イベントに割り当てられた「デフォルトの動作」をキャンセルする

テキストフィールドやコンポーネントへの入力イベントなど、「オブジェクトに反映される」直前に呼び出されるイベントがあります。
 
結果を見て、「オブジェクトへの反映」をキャンセルしたい場合は、preventDefault() メソッドを呼び出します。
 
テキストフィールドへの入力をキャンセルする例です。
 
テキストフィールドの入力反映をキャンセルする

// テキストフィールド配置
var text_field:TextField = new TextField();
stage.addChild(text_field);


text_field.border = true;
text_field.x = 10;
text_field.y = 10;
text_field.width  = 200;
text_field.height = 200;
text_field.type = TextFieldType .INPUT;


// 入力時に呼び出されるイベント
text_field.addEventListener(TextEvent.TEXT_INPUT ,function (e:TextEvent):void{

	// 入力した文字
	trace(e.text);
	
	// 動作キャンセル
	e.preventDefault();

});
 
preventDefault() メソッドが使用できるかどうか調べるには、cancelable プロパティを使用します。
 
各イベントがキャンセルできるか調べる

// テキストフィールド配置
var text_field:TextField = new TextField();
stage.addChild(text_field);


text_field.border = true;
text_field.x = 10;
text_field.y = 10;
text_field.width  = 200;
text_field.height = 200;
text_field.type = TextFieldType .INPUT;


// クリック時に呼び出されるイベント
text_field.addEventListener(MouseEvent.CLICK ,function (e:MouseEvent):void{
	trace("MouseEvent.CLICK:" + e.cancelable);
});

// 入力時に呼び出されるイベント
text_field.addEventListener(TextEvent.TEXT_INPUT ,function (e:TextEvent):void{

	trace("TextEvent.TEXT_INPUT:" + e.cancelable);

});

// 変更時に呼び出されるイベント
text_field.addEventListener(Event.CHANGE ,function (e:Event):void{

	trace("Event.CHANGE:" + e.cancelable);

});
 
■イベントの通知伝達を途中で終了する

イベントは、「キャプチャ → ターゲット → パブリック」と順番に実行されますが、この流れを途中で終了したい場合は、 stopImmediatePropagation() メソッドか stopPropagation() メソッドを使用します。
 
stopImmediatePropagation() メソッドは直ちに中断したい場合に使用します。
stopPropagation() メソッドは現在のノードの処理が終わってから中断したい場合に使用します。
 
イベントの伝達を終了する

// ムービークリップを作成
var mc0 = new MovieClip();
var mc1 = new MovieClip();
var mc2 = new MovieClip();
var mc3 = new MovieClip();
var mc4 = new MovieClip();

//  ムービークリップに名前をつける
mc0.name = "mc0";
mc1.name = "mc1";
mc2.name = "mc2";
mc3.name = "mc3";
mc4.name = "mc4";

//  子が表示リストから外れたときに呼び出されるイベントを登録
function RemovedFunc(e:Event):void{
	trace("Event.REMOVED フェーズ:" + EventPheaseGetMessage(e.eventPhase ) + " this:" + e.currentTarget.name + " target:" + e.target.name);
}
function RemovedStopPropagationFunc(e:Event):void{

	trace("Event.REMOVED フェーズ:" + EventPheaseGetMessage(e.eventPhase ) + " this:" + e.currentTarget.name + " target:" + e.target.name);

	//  イベントの流れを中断する
	e.stopPropagation();
}

mc0.addEventListener(Event.REMOVED,RemovedFunc,true);
mc1.addEventListener(Event.REMOVED,RemovedFunc,true);
mc2.addEventListener(Event.REMOVED,RemovedFunc,true);
mc3.addEventListener(Event.REMOVED,RemovedFunc,true);
mc4.addEventListener(Event.REMOVED,RemovedFunc,true);
mc0.addEventListener(Event.REMOVED,RemovedFunc);
mc1.addEventListener(Event.REMOVED,RemovedFunc);
mc2.addEventListener(Event.REMOVED,RemovedStopPropagationFunc);
mc3.addEventListener(Event.REMOVED,RemovedFunc);
mc4.addEventListener(Event.REMOVED,RemovedFunc);

//  表示リストに登録 (stage-mc0-mc1-mc2-mc3-mc4)
stage.addChild(mc0);
mc0.addChild(mc1);
mc1.addChild(mc2);
mc2.addChild(mc3);
mc3.addChild(mc4);

//  mc3 から mc4 を外す
mc3.removeChild(mc4);


//  フェーズを日本語で取得
function EventPheaseGetMessage(type:uint){
	switch(type){
	case EventPhase.CAPTURING_PHASE:
		return "キャプチャ段階";
	case EventPhase.AT_TARGET:
		return "ターゲット段階";
	case EventPhase.BUBBLING_PHASE:
		return "バブリング段階";
	}
}
 

 
 

関数の登録を外してイベント通知を止める
 


■関数の登録を外してイベント通知を止める

イベントディスパッチャーに登録した関数を外すには、 removeEventListener を使用します。
 
このメソッドを使用するには、イベントへの登録の際に使用した「イベントの種類」や「実行したい関数」などの情報が必要になります。
 
EventDispatcher.removeEventListener ( "イベントの種類" , 関数 , キャプチャーを使用するか);
第01引数 登録時に指定したイベントの種類
第02引数 登録時に指定した関数
第03引数(略可)登録時に指定したキャプチャー状態 (Boolean)
戻り値 なし
 
登録した関数を外す

function EnterFrameFunc(event){
	trace("呼び出された");
}

stage.addEventListener(Event.ENTER_FRAME ,EnterFrameFunc);
stage.removeEventListener(Event.ENTER_FRAME ,EnterFrameFunc);
 
■無名関数の登録を外す
 
イベントディスパッチャーに無名関数を渡して登録した場合、破棄するときは関数の中で arguments.callee をパラメータにして removeEventListener を呼び出すと破棄できます。
 
無名関数で登録したときは、arguments.callee をパラメータにして破棄できる

stage.addEventListener(Event.ENTER_FRAME ,function (event){
	trace("呼び出された");

	stage.removeEventListener(Event.ENTER_FRAME ,arguments.callee);
});
 

 
 

クロージャを使って関数にパラメータを保持する
 


■クロージャを使って関数にパラメータを保持する

ローカル変数を宣言している関数内で、新しく関数を動的に作成すると、ローカル変数をすべて保持する関数を作れます。
 
引数から渡される変数もローカル変数なのでそのまま保持できます。
 
ローカル変数が保持される(関数生成時の環境にアクセスできる)

function FuncCreate(param) {
	var test1 = 1;
	var test2 = 2;

	return function() {
		trace(param);
		trace(test1);
		trace(test2);
	}
}

var func = FuncCreate(0);    // 関数を動的に作成
func();                      // その関数を呼び出し
 
これを利用すれば、イベントに渡す関数にパラメータを持たせる事ができます。
 
イベントリスナー登録時にクロージャを使ってパラメータを渡す(その1)

function EnterFrameFunc (obj) {
	return function (event){
		trace("文字列:"+obj.str);
		trace("カウンタ:"+obj.count);
		obj.count ++;
	}
}

var param;
param = {
	str : "あいうえお",	// 文字列
	count : 0		// カウンタ
};
stage.addEventListener (Event.ENTER_FRAME,EnterFrameFunc(param));

param = {
	str : "かきくけこ",	// 文字列
	count : 1000		// カウンタ
};
stage.addEventListener (Event.ENTER_FRAME,EnterFrameFunc(param));
 
イベントリスナー登録時にクロージャを使ってパラメータを渡す(その2)

function EnterFrameSetFunc (target,obj) {
	// ローカル変数
	var str = obj.str;
	var count = obj.count;

	target.addEventListener (Event.ENTER_FRAME,function(e){
		trace("文字列:"+str);
		trace("カウンタ:"+count);
		count ++;
	});
}

var param;
param = {
	str : "あいうえお",	// 文字列
	count : 0		// カウンタ
};
EnterFrameSetFunc(stage,param);

param = {
	str : "かきくけこ",	// 文字列
	count : 1000		// カウンタ
};
EnterFrameSetFunc(stage,param);
 

 
 

手動的にイベントを発行する
 


■手動的にイベントを発行する

通常は、イベントに登録した関数は Flash Player から自動的に呼び出されますが、プログラムから手動的に呼び出す事もできます。
 
1.パラメータを格納するためのイベントオブジェクトを用意する
 
まず、対応する Event クラスをインスタンス化して、Event オブジェクトを作成します。
 
new Event( "イベントの種類" , [バブリング段階で実行するか] , [キャンセル可能か]);
第01引数 発行したいイベントの種類を文字列で指定
第02引数 イベントフローのバブリング段階で実行するかを Boolean 型で指定。デフォルトは false
第03引数(略可)キャンセルが可能なイベントであるかを Boolean 型で指定。デフォルトは false
戻り値 Event オブジェクト
 
例えば、Event.RESIZE イベントを発行したい場合は、Event クラスをインスタンス化します。
 
第01引数に、Event.RESIZE を指定します。
 
Event.RESIZE イベントを発行するために、Event オブジェクトを作成する

var event:Event = new Event(Event.RESIZE);
 
MouseEvent.MOUSE_UP イベントを発行したい場合は、MouseEvent クラスをインスタンス化します。
 
第01引数に、MouseEvent.MOUSE_UP を指定します。
 
Event.RESIZE イベントを発行するために、Event オブジェクトを作成する

var event:Event = new MouseEvent(MouseEvent.MOUSE_UP);
 
2.イベントを発行する
 
イベントを発行するには、dispatchEvent() メソッドを使用します。
 
引数に、イベントオブジェクトを渡します。
 
Event.RESIZEイベントを発行する例です。
 
イベントを手動で発行する

// Flash がリサイズ時に実行されるイベント
stage.addEventListener(Event.RESIZE,function(e:Event):void{
	trace("Event.RESIZEイベントが呼び出された");
});

// Event.RESIZE イベントを発行
stage.dispatchEvent(new Event(Event.RESIZE));
 
MouseEvent.MOUSE_UP イベントを発行する例です。
 
発行前に Event オブジェクトに何らかのパラメータを格納しておけば、イベントに登録した関数側で取り出すことができます。
 
イベントを手動で発行する

// マウスの左ボタンを離したときに実行されるイベント
stage.addEventListener(MouseEvent.MOUSE_UP,function(e:MouseEvent):void{
	trace("MouseEvent.MOUSE_UPイベントが呼び出された: localX:" + e.localX + " localY:" + e.localY);
});

// MouseEvent.MOUSE_UP イベント用のイベントオブジェクトを作成
var mouse_up_event:MouseEvent = new MouseEvent(MouseEvent.MOUSE_UP);

// 何らかのパラメータを持たせる
mouse_up_event.localX = 123;
mouse_up_event.localY = 456;

// MouseEvent.MOUSE_UP イベントを発行
stage.dispatchEvent(mouse_up_event);
 
■自作のイベントを登録して発行する
 
イベントを自作する事ができます。
 
1.イベントの名称を決める
 
好きなイベントの名称を決めます。
 
イベントの名称は必ずユニーク(唯一)な名称である必要があります。
 
ここでは、"my_event_exec" とします。
 
2.Event クラスを用意する
 
Event クラスをそのまま使用するのもいいですが、 何らかの専用のパラメータを持たせたい場合は、Event クラスから派生させた自作のクラスを用意します。
 
ここでは、MyEvent という自作クラスを用意してみます。my_data というプロパティを追加しています。
 
Event クラスから派生させた MyEvent クラスを用意する

package  {

	import flash.events.Event;

	public class MyEvent extends Event {

		public var my_data:String;

		public function MyEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false){
			// 親のコンストラクタを実行
			super(type,bubbles,cancelable);
		}

	}
	
}
 
3.イベントに関数を登録する
 
ステージに "my_event_exec" イベントを追加してみます。
 
実行したい関数の引数には、先ほど作成した MyEvent クラスを指定します。
 
ステージに "my_event_exec" イベントを追加する

// "my_event_exec" イベントに関数を登録する
stage.addEventListener("my_event_exec",function(e:MyEvent):void{

	trace("my_event_exec イベントが実行された:" + e.my_data);

});
 
4.パラメータを格納するための Event オブジェクトを用意する
 
Event クラスをインスタンス化して、Event オブジェクトを用意します。第01引数に、イベント名称を指定します。
 
登録した関数に渡したいパラメータがあれば、Event オブジェクトのプロパティにデータを格納しておきます。
 
ここでは、MyEvent クラスをインスタンス化します。第01引数に "my_event_exec" を渡します。
 
 
Event オブジェクトを用意する

// Event オブジェクトを作成する
var my_event:MyEvent = new MyEvent("my_event_exec");

// 適当なパラメータを渡す
my_event.my_data = "イベントテスト";
 
5.イベントを発行する
 
イベントを発行したいタイミングが訪れれば、dispatchEvent() メソッドを呼び出します。引数に、Event オブジェクトを渡します。
 
ここでは引数に、MyEvent オブジェクトを渡します。
 
イベント発行する

// "my_event_exec" イベントに関数を登録する
stage.addEventListener("my_event_exec",function(e:MyEvent):void{

	trace("my_event_exec イベントが実行された:" + e.my_data);

});

// Event オブジェクトを作成する
var my_event:MyEvent = new MyEvent("my_event_exec");

// 適当なパラメータを渡す
my_event.my_data = "イベントテスト";

// イベントを発行する
stage.dispatchEvent(my_event);
 
6.イベントのキャンセルに対応する
 
dispatchEvent() メソッドの戻り値からイベントが中断されたかが分かります。
 
true であれば正常にイベントが実行された事がわかります。false であれば、イベントが中断されたかキャンセルされたことがわかります。
 
イベントに登録した関数内で preventDefault() メソッドを呼び出すと、キャンセルを通知する事ができます。
 
preventDefault() メソッドによるイベントのキャンセルを有効にするには、Event クラスのコンストラクタの第03引数に true を指定します。
 
イベントがキャンセルされたか取得する

// "my_event_exec" イベントに関数を登録する
stage.addEventListener("my_event_exec",function(e:MyEvent):void{

	trace("my_event_exec イベントが実行された:" + e.my_data);

	// イベントをキャンセルする
	e.preventDefault();

});

// Event オブジェクトを作成する
var my_event:MyEvent = new MyEvent("my_event_exec",false,true);

// 適当なパラメータを渡す
my_event.my_data = "イベントテスト";

// イベントを発行する
var result:Boolean = stage.dispatchEvent(my_event);

// イベントの結果から処理を分岐する
if(result){
	trace("my_event_exec イベントは正常に実行された");
}else{
	trace("my_event_exec イベントはキャンセルされた");
}
 

 


HAKUHIN's home page バナー http://hakuhin.jp/
(c) Hakuhin & 日新礼符 2002-2011 解像度1024×768以上 IE8.0以上推奨
/ 閲覧中: