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。因此,每个影片剪辑中的每次点击都会调用doSomething,并将9作为参数传递。这不是我想要的。

我认为创建自定义事件应该可以工作,但是当触发 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

非常感谢这个有用的提示,这种技术比类解释更容易理解。

对我来说,我刚刚开始使用这种技术来解决计时器数组和视口数组之间的链接关系的新代码算法,并通过频繁更改其中的文本来更新状态,通过将 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 回答
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动态对象(即MovieClip),但会让您失望(即Sprite),迫使您为每种类型构建一个完整的自定义扩展对象/事件。

该解决方案处理每个“可收听”的对象和事件。这个答案有更多的细节和例子。

于 2012-12-04T23:17:34.133 回答