ActionScript 3.0 のイベント伝播を学ぶ
2008 年 4 月 14 日 月曜日
AS3 のイベント処理。AS2 時代の EventDispatcher 経験で、なあなあに作って来たのですが、諸般の事情で bubble とか useCapture を知る事に決めました。
何はともあれ Adobe の公式資料です。しっかり書いてあります。
- Flash CS3 ドキュメンテーション ActionScript 3.0 のプログラミング > イベントの処理 > イベントフロー
- Event - ActionScript 3.0 コンポーネントリファレンスガイド
- EventDispatcher - ActionScript 3.0 コンポーネントリファレンスガイド
- キャプチャ段階: Stage からイベントターゲットまでのオブジェクトに於けるイベント伝播
- ターゲット段階:イベントターゲットに於けるイベント伝播
- バブリング段階:イベントターゲットから Stage までのオブジェクトに於けるイベント伝播
そしてイベントを実際に扱うクラス・メソッドの解説も読みます。
EventDispatcher
addEventListener(type:String, listener:Function,
useCapture:Boolean = false):void
useCapture:Boolean (default = false) ― リスナーが、キャプチャ段階、またはターゲットおよびバブリング段階で動作するかどうかを判断します。useCapture を true に設定すると、リスナーはキャプチャ段階のみでイベントを処理し、ターゲット段階またはバブリング段階では処理しません。useCapture を false に設定すると、リスナーはターゲット段階またはバブリング段階のみでイベントを処理します。3 つの段階すべてでイベントを受け取るには、addEventListener を 2 回呼び出します。useCapture を true に設定して 1 度呼び出し、useCapture を false に設定してもう一度呼び出します。
Event
Event(type:String, bubbles:Boolean = false)
bubbles:Boolean (default = false) ― Event オブジェクトがイベントフローのバブリング段階で処理されるかどうかを判断します。デフォルト値は false です。
それぞれもっと引数が付くのですが、今回の話では割愛です。
addEventListener の useCapture についてまとめます。
- デフォルト( false )ではターゲット/バブリング段階のみ処理が行われる。
- true ならキャプチャ段階のみ処理が行われる。
- 故に、総ての段階を対象とするなら true / false で addEventListener を二回呼ぶ。
それでは次にEvent の bubbles 。
デフォルトの Event オブジェクトはバブリング段階で処理されない事が分かります。
ここは更に Event の定数らを見る事にします。すると、イベントによっては bubbles = true のイベントオブジェクトが在る事が分かります。
例えば Event.REMOVED は true です。
(ちなみに Event.REMOVED_FROM_STAGE は false )
ここまで得られた情報でイベント伝播の概要は掴めたので、何か書いてみます。
あるオブジェクトで Event.REMOVED_FROM_STAGE と Event.REMOVED が発生する毎に trace するコードです。
addEventListener の解説に在った様に true / false で二回呼んで総ての段階を対象とします。
package {
import flash.display.Sprite;
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
public class ExeEvent extends MovieClip{
var _grid:Sprite;
public function ExeEvent(){
_grid = new Sprite();
_grid.graphics.lineStyle( 4, 0x333333 );
_grid.graphics.drawRect( 0, 0, 200, 200 );
addChild( _grid );
var addTF:TextField = new TextField();
addTF.text = "ADD";
var removeTF:TextField = new TextField();
removeTF.text = "REMOVE";
removeTF.x = addTF.width;
addChild( addTF );
addChild( removeTF );
addTF.addEventListener( MouseEvent.CLICK, _addButton );
removeTF.addEventListener( MouseEvent.CLICK, _removeButton );
stage.addEventListener( Event.REMOVED, _onRemoved, true );
stage.addEventListener( Event.REMOVED, _onRemoved, false );
_grid.addEventListener( Event.REMOVED, _onRemoved, true );
_grid.addEventListener( Event.REMOVED, _onRemoved, false );
stage.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, true );
stage.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, false );
_grid.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, true );
_grid.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, false );
}
private function _onRemoved( event:Event ):void {
trace( “# _onRemoved ” + event.currentTarget.name);
trace( event.toString() );
}
private function _onRemovedFromStage( event:Event ):void {
trace( “$ _onRemovedFromStage ” + event.currentTarget.name);
trace( event.toString() );
}
private function _addButton( event:MouseEvent ):void {
var button:Sprite = new Sprite();
button.graphics.beginFill( 0xcccccc );
button.graphics.drawCircle( 10, 10, 10 );
button.graphics.endFill();
button.x = _grid.width * Math.random();
button.y = _grid.height * Math.random();
_grid.addChild( button );
button.addEventListener( Event.REMOVED, _onRemoved, true );
button.addEventListener( Event.REMOVED, _onRemoved, false );
button.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, true );
button.addEventListener( Event.REMOVED_FROM_STAGE, _onRemovedFromStage, false );
}
private function _removeButton( event:MouseEvent ):void {
if ( _grid.numChildren > 0 ) {
_grid.removeChildAt( 0 );
}
}
}
}
次が出力例です。
# _onRemoved null
[Event type="removed" bubbles=true cancelable=false eventPhase=1]
# _onRemoved instance1
[Event type="removed" bubbles=true cancelable=false eventPhase=1]
# _onRemoved instance4
[Event type="removed" bubbles=true cancelable=false eventPhase=2]
# _onRemoved instance1
[Event type="removed" bubbles=true cancelable=false eventPhase=3]
# _onRemoved null
[Event type="removed" bubbles=true cancelable=false eventPhase=3]
$ _onRemovedFromStage null
[Event type="removedFromStage" bubbles=false cancelable=false eventPhase=1]
$ _onRemovedFromStage instance1
[Event type="removedFromStage" bubbles=false cancelable=false eventPhase=1]
$ _onRemovedFromStage instance4
[Event type="removedFromStage" bubbles=false cancelable=false eventPhase=2]
event.currentTarget.name を出力させましたが、Stage は name 属性が無いので null 出力です。eventPhase の1・2・3がキャプチャ・ターゲット・バブリング段階に対応しています(eventPhase参照)。- キャプチャ段階: Stage からイベントターゲットまでのオブジェクトに於けるイベント伝播
- ターゲット段階:イベントターゲットに於けるイベント伝播
- バブリング段階:イベントターゲットから Stage までのオブジェクトに於けるイベント伝播








