7

この質問は、MouseEvent.CLICK イベント タイプだけに関連するものではなく、AS3 に既に存在するすべてのイベント タイプに関連しています。カスタム イベントについてはよく読みましたが、これまで自分がやりたいことを実行する方法がわかりませんでした。説明しようと思います。ご理解いただければ幸いです。

これが私の状況の実例です:

for(var i:Number; i < 10; i++){
    var someVar = i;
     myClips[i].addEventListener(MouseEvent.CLICK, doSomething);
}

function doSomething(e:MouseEvent){ /* */ }

しかし、 someVarをパラメーターとしてdoSomethingに渡すことができるようにしたいと考えています。だから私はこれを試しました:

for(var i:Number; i < 10; i++){

    var someVar = i;
    myClips[i].addEventListener(MouseEvent.CLICK, function(){
        doSomething(someVar);
    });
}

function doSomething(index){ trace(index); }

この種の作品は期待どおりではありません。関数クロージャーにより、MouseEvent.CLICK イベントが実際に発生したとき、forループはすでに終了しており、someVarは最後の値 (例では9 ) を保持しています。したがって、各ムービー クリップ内でクリックするたびに、パラメータとして9を渡してdoSomethingが呼び出されます。そして、それは私が望むものではありません。

カスタム イベントを作成すればうまくいくはずだと思いましたが、MouseEvent.CLICK イベントが発生したときにカスタム イベントを発生させてパラメータを渡す方法が見つかりませんでした。今はそれが正しい答えかどうかわかりません。

どうすればいいですか?

4

6 に答える 6

7

追加のパラメータを使用して独自のイベントを作成するには、イベントクラスを拡張する必要があります。addEventListener(無名関数)内に関数を配置することは、メモリリークのレシピであり、これは良くありません。以下をご覧ください。

import flash.events.Event;

//custom event class to enable the passing of strings along with the actual event
public class TestEvent extends Event
{
    public static const TYPE1 :String = "type1";
    public static const TYPE2 :String = "type2";
    public static const TYPE3 :String = "type3";

    public var parameterText:String;

    public function TestEvent (type:String, searchText:String)
    {
        this.parameterText = searchText;
        super(type);
    }

}

次のような新しいイベントを作成するとき

dispatchEvent(new TestEvent(TestEvent.TYPE1, 'thisIsTheParameterText'))" ;

その後、このようなイベントを聞くことができます

someComponent.addEventListener(TestEvent.TYPE1, listenerFunction, true , 0, true);

関数'listenerFunction'の中にevent.parameterTextにパラメータが含まれます。

したがって、myClipsコンポーネント内では、カスタムイベントを発生させ、Clickイベントではなくそのイベントをリッスンします。

于 2009-01-09T16:14:36.627 に答える
6

アプリケーションについて詳しく知らなくても、ターゲットを使用してパラメーターを渡すか、MouseEventを拡張する必要があるようです。ただし、前者の方が一般的な慣習に沿ったものになります。したがって、たとえば、「クリップ」オブジェクトに整数のパブリックプロパティを公開した場合(それが何であれ):

public class MyClip
{
   public var myPublicProperty:int;

   public function MyClip() { //... }
}

for (var i:int = 0; i < 10; i++)
{
   myClips[i].myPublicProperty = i;
   myClips[i].addEventListener(MouseEvent.CLICK, doSomething);
}

...次に、イベントリスナーで、イベントのtargetまたはcurrentTargetプロパティ(この場合はおそらくcurrentTarget)を使用してそのプロパティを取得できます。

function doSomething(event:MouseEvent):void
{
   trace(event.currentTarget.myPublicProperty.toString());
}

それはそれをするべきです!幸運を。

于 2009-01-09T03:18:51.427 に答える
3
    private function myCallbackFunction(e:Event, parameter:String):void
    {
         //voila, here's your parameter
    }

    private function addArguments(method:Function, additionalArguments:Array):Function 
    {
         return function(event:Event):void {method.apply(null, [event].concat(additionalArguments));}
    }

    var parameter:String = "A sentence I want to pass along";
    movieClip.addEventListener(Event.COMPLETE, addArguments(myCallbackFunction, [parameter] ) );

AS3 の動的関数構築を利用します。

于 2011-01-03T00:49:06.480 に答える
2

次のように、変数クロージャーを提供する関数からハンドラーを取得することで、これを実現できます。

for (var i=0; i<5; i++) {
    myClips[i].addEventListener( MouseEvent.CLICK, getHandler(i) );
}

function getHandler(i) {
    return function( e:MouseEvent ) {
        test(i);
    }
}

function test( j ) {
    trace("foo "+j);
}

また、これが新しい閉鎖を作成する理由については、この同様の質問に対する受け入れられた回答の説明を確認することをお勧めします。

于 2009-01-09T01:29:27.917 に答える
1

あなたの主な目標は、実際にはカスタム MouseEvent.CLICK を作成することではなく、パラメーターを関数に渡すことだと思います。複雑に何かを作成したり拡張したりする必要はありません。それを行うためのシンプルでクロージャーのトラブルのない方法があります。

関数を次のようにするだけです。

function doSomething(index:Number):Function {
  return function(e:MouseEvent):void {
    // Use "e" and "index" here. They'll be unique for each addEventListener()
    trace(index);
  }
}

この手法は、addEventListener を使用できる任意の AS3 イベント タイプに関連付けることができます。

そして、次のように追加できます。

var functionsDoSomething:Object;

for (var i:Number = 0; i < 10; i++) {
  var someVar:Number = i;
  functionsDoSomething[i] = doSomething(someVar);
  myClips[i].addEventListener(MouseEvent.CLICK, functionsDoSomething[i]);
}

doSomething(someVar)で直接使用できますaddEventListener()が、追加したのと同じ方法で後で削除できるため、変数に保持することをお勧めします。

for (i = 0; i < 10; i++) {
  myClips[i].removeEventListener(MouseEvent.CLICK, functionsDoSomething[i]);
}

一般的に使用されるe.currentTarget.someCustomPropertyのは動的オブジェクト (つまり、ムービークリップ) では機能しますが、他のもの (つまり、スプライト) ではがっかりするため、すべてのタイプのカスタム拡張オブジェクト/イベント全体を構築する必要があります。

このソリューションは、すべての「リッスン可能な」オブジェクトとイベントを処理します。そして、この回答には詳細と例があります。

于 2012-12-04T23:17:34.133 に答える
1

この便利なヒントに感謝します。このテクニックは、クラスの説明よりも理解しやすいものです。

私にとっては、この手法を使用して新しいコード アルゴリズムを開始し、タイマー配列とビューポート配列の間のリンク関係を解決し、タイマー イベントで ID を渡すことにより、それらの内部のテキストを頻繁に変更してステータスを更新しました。

このような:

    var view:Object=[];

    for(var i:uint=0;i<Camera.names.length;i++){

    view[i]=getChildByName("Cam"+i);

    //_________ Add Text _________
    var tf:TextField = new TextField();
    tf.autoSize = TextFieldAutoSize.LEFT;
    tf.textColor=0xffffff;
    view[i].tf=view[i].addChild(tf);

    //_________ Add Timer _________
    var t:Timer = new Timer(1000);
    view[i].timer=t;
    view[i].timer.start();
    view[i].timer.addEventListener(TimerEvent.TIMER, addArg(i)); 
}

function addArg(adi:uint):Function {
    return function(event:TimerEvent):void {
        updatecamstatus(adi);
    }
}
function updatecamstatus(vH:uint):void {
   with (view[vH]){
    tf.text="Cam" + vH + "\n";
    tf.appendText("activityLevel: " + videosource.activityLevel + "\n"); 
    tf.appendText("motionLevel: " + videosource.motionLevel + "\n"); 
   }
}
于 2011-04-05T21:15:29.860 に答える