« BUILDUP! | Home | FireFoxでJavaScriptのon/offを簡単に切り替える(for開発) »

Apr 222008

addEventListenerで一緒に引数を渡したい

と思うのはオデだけですか?
なんか方法あるのかしら??

たとえばボタンが2つあってhandlerを同じmethodに引き渡すとして

bt.addEventListener(flash.events.MouseEvent.CLICK,onClick);
bt.skill="aho";
bt2.addEventListener(flash.events.MouseEvent.CLICK,onClick);
bt2.skill="baka";
function onClick(e) {
	trace(e.target.skill);
	trace(e.currentTarget.skill);
}
みたいに書いたりするんだけど、 これ MovieClipがdynamicだからいいけど(独自クラスだったらそれ様の変数を定義しないと) そして 単純な構造だからいいけど(Spriteが入れ子になってたらとか) 普通はこんな簡単なことにはならない。 しかもいちいち変数を定義するのが面倒。 これはイベントドリブンだけの話ではなく、データドリブン時にも同じような不便さを感じる。 (昔自分で作っていたイベントクラスがそういう形だったからというだけなのだけど)

これ

bt2.addEventListener(flash.events.MouseEvent.CLICK,onClick,"aho");
とか出来ないのだろうか??

いや一応

bt2.addEventListener(flash.events.MouseEvent.CLICK,function(){onClick2("baka")});
function onClick2(skill) {
	trace("onClick2",skill);
}
とかすればできるけど、これはまたこれで冗長でなんか汚い。

直感的っぽいのは"flash.events.MouseEvent.CLICK"で生成されるEventに何かしら動的に変数を埋め込むーみたいな感じだけど、この辺やろうと思ったらdispatchのタイミングになるから、EventDispatcherから手を入れないといけないのでヤダ。

いやなんか普通に出来そうな気もするのだけど、こういうことってプログラムの世界ではどういう呼称なのかさっぱり分からないから検索出来なかった。
なんかふつーにできることだったらめっさ恥ずかしいんだけど・・・。

::追記@08/04/23 09:55:38
simoさんから教えていただいたサイト
AS3:26.イベント発生時の処理に引数を渡す
に書かれているやりかた

bt3.addEventListener(flash.events.MouseEvent.CLICK,onClick3("baka"));
function onClick3(str:String) {
	return function (e:MouseEvent):void{;
	trace("str",str);
	trace(e.target.name);
	} ;
}
が個人的にはかなりしっくり来ました。引数、イベントの両方の取得が標準クラスで実装できるので複数人で作業しているときでもクラスの引き渡しもなく簡単。ただ引数で使用するものをGC対象にする場合は削除していく順番にちょっと注意する必要があるかもしれないです。

::追記@08/04/23 10:23:26
ちと追加で色々調べてみる。

bt2.addEventListener(flash.events.MouseEvent.CLICK,function(e){onClick2(e,"baka")});
って書き方をしてもいけるわけですが、まぁあまりきれいではない。 というか、それよりもhandlerを統一して、その中で分岐させるようにしたい場合などは
bt5.addEventListener(flash.events.MouseEvent.CLICK,onClick5("dog","brown"));
bt6.addEventListener(flash.events.MouseEvent.CLICK,onClick5("cat","white"));
function onClick5(...args):Function
{
	return function (e:MouseEvent):void{
	if(args[0]=="dog")
	{
		trace("dog");//犬の処理
	}
	else if(args[0]=="cat")
	{
		trace("cat");//猫の処理
	}
	} ;
}
っとか出来るデスね。

しかし問題はhandlerが無名関数なのでremoveEventListenerが出来ないという部分。
なんか良い方法はないかしら?

17 Comments

はじめまして。いつもblogを拝見させて頂いてます。

下記のエントリーにて解決方法が記載されていますので参考にされてはどうでしょうか。

http://www.ringsbell.net/flash/as3/event.php

引数は、常にaddEventListenerに指定したflash.events.***Eventクラスのインスタンスですので、***Eventクラスを継承した必要なOriginalEventクラスを作れば、リスナーの引数にパラメータを渡せるのでわ。


addEventListener(OriginalEvent.CLICK ,onClick)とすれば。


import flash.events.***Event;

public class OriginalEvent extends ***Event{
public var info:Object;

......
......

piblic fucntion CustomEvent(type:String , info:Object,.....){
super(type , ....);
this.info=info;
}
}
みたいな感じで。

>simoさん
ありがとうございます。最後の書き方は目から鱗でした。イベントも引数も両方とれて便利ですね。

>通りすがりさん
これに似たやり方はすでにやってるんですが、このやり方ではdispatchのタイミングでnew Eventして、infoを指定しないといけないですよね??となると例えばMovieClipをextendしていた場合、その中のdispatchEvent部分をoverrideしないといけないんじゃないかと思います。これはエントリー中の
>この辺やろうと思ったらdispatchのタイミングになるから、EventDispatcherから手を入れないといけないのでヤダ。
って部分です。
理解がずれていたらスイマセン。

Function内で、arguments.calleeとすれば、実行中の関数の参照がとれます。
ですので、イベント受け取った際には、removeListenerするチャンスはあります。

stage.addEventListener(
MouseEvent.MOUSE_DOWN,
function():void
{
stage.removeEventListener(MouseEvent.MOUSE_DOWN, arguments.callee);
}
);

>imajukさん
おお、すごいw これで何か実用的な形に落とし込めないかしら?やってみよっと。アリガトゴザイマス。

引数判定でremove出来ないかと思ってやってみたんですが、当然と言うか引数が違うから削除するためのイベントがaddされてremoveされるだけで意味がなかった・・・汗
EventDispatcherクラスから登録されたイベントとハンドラーが取得できれば良いのに・・。何故出来ないのだろうか??

EventDispatcherのaddEventListenerの
this[queueName].push(handler);
の部分をthisじゃなくって、queuesとかObjectのなかに格納すれば逆に参照できるような気がするのだけど、GC的に不具合がでるのかしら?
AS2のころbroadCasterを拡張してたときはそんな感じで一括除去とか出来るようにつくってたんだけど、無理なのかしら??

あ、違うこれ
mx.events.EventDispatcher
だった・・・。
AS3のEventDipatcherは何故かオデの環境では
C:\Program Files\FlashDevelop\FirstRun\Library\AS3\intrinsic\flash\events
にあるのだが・・・何故?
ちなみに
Generated by Asapire v1.0 - brainy 2007
って書いてあってasの記述は関数定義のみ。カスタムできないのかしら?

サブクラス拡張だと継承しているものが多すぎて面倒なのでそのものを書き換えられたらいいんだけど、prototypeで上書きとか駄目かしら?っつーかソースが見たい。

ウーム、訳分からなくなってきた。
中止w

removeEventListenerする必要がある場合には無名関数で引数渡すのはやめた方がよさそうだという結論に至りましたw

最近わかったのですが、リスナとして匿名関数を渡すのは結構ヤバいですw
http://www.imajuk.com/blog/archives/2008/04/post_3.html

ご報告ありがとうございます。そですね、結局自分も実行してもヘビーな処理は別関数に引き渡す、もしくは入れ替えが激しい場合(removeする場合)は使用しないという方向で結論出しました。
他にも色々興味深い検証をたくさん行われていますねーー。
勉強させてもらいます!

まったく同じ事を考えており、検索でたどり着きました。

とても参考になりました有難うございます。

いえー、お役に立てたのなら良かったです。

間抜けにもいちいち変数を定義していたので、とても勉強になりました。ありがとうございます。

実は最近、普通に関数を分ける書き方に復帰しつつあります(汗
クロージャーな書き方をすると後から修正が結構ゴチャゴチャになってしまうことが多くて、結局一つ一つ明示的にfunctionで分けているというのが現状であります。

Leave a comment

Search and Archives