AS3S.ORG

ACTIONSCRIPT 3.0 SOURCES

getter/setterを利用してイベントリスナーを動的に切り替える

AS2では

Mouse.addListener(this);

とすることで、MouseDown時に、this.onMouseDownメソッドが呼ばれるようになります。

function onMouseDown() {
    trace("default");
}
function test() {
    trace("test");
}
Mouse.addListener(this);
this.onMouseDown = test;

などとすることで、addListenerした後でもonMouseDownメソッドを動的に切り替えることができます。

AS3で採用されたイベントモデルでは、addEventLisntener時にイベントリスナーの参照を引数として指定するようになり、また、ほかのモダンな言語と同様、参照渡し(call by reference)ができないため、以下のようなコードではAS2に相当する動的なリスナーの切り替えができません。

function onMouseDown(event:MouseEvent):void {
    trace("default");
}
function test(event:MouseEvent):void {
    trace("test");
}
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
onMouseDown = test; //意味なし

上記の例では、addEventListenerで渡されるのは、その時点でのonMouseDownの値なので、その後にonMouseDownの値を変えても意味がありません。
【参考】AS3では関数の引数はすべて値渡し(call by value)である

そこで、下記のようにgetter/setterメソッドを利用することで同じような動作が実現できます。
この例では、最初のMouseDownと2回目以降のMouseDownで呼ばれるリスナー関数が切り替わります。

package {
    import flash.display.Sprite;
    import flash.events.MouseEvent;

    public class DynamicListenerSample extends Sprite {

        private var _onMouseDown:Function;
        private function onMouseDownHandler(event:MouseEvent):void {
            if (_onMouseDown!=null) _onMouseDown(event);
        };
        private function get onMouseDown():Function {
            return onMouseDownHandler;
        }
        private function set onMouseDown(func:Function):void {
            _onMouseDown = func;
        }

        public function DynamicListenerSample() {
            onMouseDown = test;
            stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
        }

        private function test(event:MouseEvent):void {
            trace("This is test.");
            onMouseDown = test2;
        }

        private function test2(event:MouseEvent):void {
            trace("This is test2.");
            stage.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
        }

    }
}

▼出力結果
This is test. ←1回目のMouseDown
This is test2. ←2回目のMouseDown
(3回目以降は呼ばれない)

(追記)
getterで無名関数を返すようにしていましたが、そうするとremoveEventListenerでも新たに無名関数が作られてしまいremoveEventListenerできなくなるので、上記のとおり修正しました。

Written by admin

February 11th, 2008 at 11:10 pm

Posted in misc.

Leave a Reply