2009-01-08 15 views
7

Esta pregunta no se refiere solo al tipo de evento MouseEvent.CLICK sino a todos los tipos de eventos que ya existen en AS3. Leí mucho sobre eventos personalizados, pero hasta ahora no podía entender cómo hacer lo que quiero hacer. Voy a tratar de explicar, espero que entienda:Cómo crear un evento personalizado MouseEvent.CLICK en AS3 (pasar los parámetros a la función)?

Aquí es una ilustración de mi situación:

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

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

Pero yo quiero ser capaz de pasar somevar como un parámetro para doSomething. Así que probé esto:

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

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

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

Este tipo de trabajo funciona pero no como esperaba. Debido a los cierres de funciones, cuando los eventos MouseEvent.CLICK se activan, el para ya se ha terminado y someVar contiene el último valor, el número en el ejemplo. Por lo tanto, cada clic en cada clip de película llamará a doSomething pasando como parámetro. Y no es lo que quiero

Pensé que la creación de un evento personalizado debería funcionar, pero luego no pude encontrar una forma de activar un evento personalizado cuando el evento MouseEvent.CLICK se dispara y pasarle el parámetro. Ahora no sé si es la respuesta correcta.

¿Qué debo hacer y cómo?

+0

Para cualquiera que esté investigando esto, agregué un ejemplo de código rápido sobre pasar parámetros a una función aquí: http://rocketwidget.com/how-to-pass-additional-parameters-to-an-event-listener- in-flex/ –

Respuesta

6

Sin conocer más acerca de su aplicación, parece que debería usar el objetivo para pasar parámetros o extender MouseEvent. Sin embargo, el primero estaría más en línea con la práctica común. Así, por ejemplo, si se expone una propiedad pública número entero en el objeto "pinza" (cualquiera que sea):

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); 
} 

... y luego, en su detector de eventos, se puede recuperar ese establecimiento a través de la diana o propiedad currentTarget del evento (probablemente currentTarget, en su caso):

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

Eso debería hacerlo! Buena suerte.

2

Esto se puede hacer por conseguir el controlador de salida de una función que da el cierre variables, como esto:

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); 
} 

Además, en cuanto a por qué esto crea un nuevo cierre, es posible que desee comprobar la explicación en la respuesta aceptada al this similar question.

7

Realmente necesita ampliar la clase de evento para crear su propio evento con parámetros adicionales. Colocar funciones dentro de addEventListener (funciones anónimas) es una receta para las pérdidas de memoria, lo cual no es bueno. Eche un vistazo a lo siguiente.

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); 
    } 

} 

cuando se crea un nuevo evento como

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

a continuación, puede escuchar para ese evento como este

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

y dentro de la función 'listenerFunction' event.parameterText contendrá tu parámetro

así que dentro de su componente myClips dispararía el evento personalizado y escucharía ese evento y no el evento Click.

+0

¿Por qué las funciones anónimas serían una causa probable de pérdidas de memoria, exactamente? – fenomas

+0

no tiene ninguna referencia a la función, que combinada con weakReference en el eventListener que establece el valor predeterminado en false puede, si no tiene cuidado, provocar pérdidas de memoria. se considera mala práctica + cualquier flashplayer 9.115 o inferior tiene un error que causa una pérdida de memoria para funciones anónimas. – kenneth

+0

Esto todavía no explica cómo dispararía/enviaría este evento personalizado cuando se trata de un evento MouseEvent.El evento CLICK ocurre. ¿Me estoy perdiendo de algo? – fromvega

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])); 

Aproveche la construcción de funciones dinámicas en AS3.

+0

esto es excelente. Lo he implementado en un proyecto. – dubbeat

+0

¡Gracias, muy muy útil! – Drala

1

Muchas gracias por estos útiles consejos, esta técnica es mejor de entender que la explicación de las clases.

por mi Acabo de iniciar un nuevo algoritmo de código usando esta técnica para resolver la relación de enlace entre los temporizadores y la matriz de viewports, y actualizo el estado al cambiar texto dentro de ellos con frecuencia, pasando ID con eventos de temporizadores.

así:

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"); 
    } 
} 
1

veo su objetivo principal no es en realidad para crear una costumbre MouseEvent.CLICK, pero para pasar un parámetro a la función. No necesita crear o extender algo de manera complicada. Hay una manera simple y sin problemas de cierre para hacerlo.

Simplemente haga su función como esta:

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

Esta técnica puede referirse a cualquier tipo de evento AS3 puede utilizar addEventListener sucesivamente.

Y ahora se puede añadir de esta manera:

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]); 
} 

El doSomething(someVar) se puede utilizar directamente en addEventListener(), pero es mejor mantenerlo en una variable, ya que será capaz de eliminar más tarde el mismo de manera que agregó que:

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

Las utilizados comúnmente e.currentTarget.someCustomProperty obras para objetos dinámicos (es decir, de clip de película), pero le fallará en cualquier otra cosa (es decir, Sprite), lo que obligó a construir un objeto/evento extendida por encargo del conjunto de cada tipo

Esta solución se ocupa de todos los objetos y eventos "escuchables". Y this answer tiene más detalles y ejemplos sobre él.

Cuestiones relacionadas