Domanda

Questa domanda non riguarda solo il tipo di evento MouseEvent.CLICK ma tutti i tipi di eventi già esistenti in AS3. Ho letto molto sugli eventi personalizzati ma fino ad ora non sono riuscito a capire come fare quello che voglio fare. Proverò a spiegare, spero che tu capisca:

Ecco un esempio della mia situazione:

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

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

Ma voglio essere in grado di passare someVar come parametro a doSomething . Quindi ho provato questo:

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

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

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

Questo tipo di lavori funziona ma non come mi aspetto. A causa della chiusura delle funzioni, quando gli eventi MouseEvent.CLICK vengono effettivamente attivati, il ciclo for è già terminato e someVar contiene l'ultimo valore, il numero 9 nell'esempio. Quindi ogni clic in ogni clip filmato chiamerà doSomething passando 9 come parametro. E non è quello che voglio.

Ho pensato che la creazione di un evento personalizzato avrebbe dovuto funzionare, ma poi non sono riuscito a trovare un modo per generare un evento personalizzato quando l'evento MouseEvent.CLICK viene generato e passare il parametro ad esso. Ora non so se è la risposta giusta.

Cosa devo fare e come?

È stato utile?

Soluzione

Senza sapere di più sulla tua applicazione, sembra più che dovresti usare la destinazione per passare i parametri o estendere MouseEvent. Il primo sarebbe tuttavia più in linea con la pratica comune. Ad esempio, se hai esposto una proprietà pubblica intera sul tuo " clip " oggetto (qualunque esso sia):

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

... e quindi, nel tuo listener di eventi, potresti recuperare quella proprietà usando la proprietà target o currentTarget dell'evento (probabilmente currentTarget, nel tuo caso):

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

Dovrebbe farlo! Buona fortuna.

Altri suggerimenti

Devi davvero estendere la classe dell'evento per creare il tuo evento con parametri extra. Inserire le funzioni all'interno di addEventListener (funzioni anonime) è una ricetta per le perdite di memoria, il che non va bene. Dai un'occhiata a quanto segue.

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

}

quando crei un nuovo evento come

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

puoi quindi ascoltare l'evento come questo

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

e all'interno della funzione 'listenerFunction' event.parameterText conterrà il tuo parametro.

quindi, all'interno del componente myClips, attiverai l'evento personalizzato e ascolterai l'evento e non l'evento Click.

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

Approfitta della costruzione della funzione dinamica in AS3.

È possibile ottenere questo risultato estraendo il gestore da una funzione che fornisce la chiusura variabile, in questo modo:

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

Inoltre, per il motivo per cui questo crea una nuova chiusura, potresti voler controllare la spiegazione nella risposta accettata a questa domanda simile .

Grazie mille per questi utili suggerimenti, questa tecnica è meglio capire della spiegazione delle classi.

per me ho appena iniziato un nuovo algoritmo di codice usando questa tecnica per risolvere la relazione di collegamento tra array di timer e array di finestre e aggiornare lo stato modificando frequentemente il testo al loro interno, passando ID con eventi timer.

in questo modo:

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

Vedo che il tuo obiettivo principale non è effettivamente quello di creare un MouseEvent.CLICK personalizzato, ma di passare un parametro alla funzione. Non è necessario creare o estendere complicatamente nulla. C'è un modo semplice e senza problemi di chiusura per farlo.

Rendi la tua funzione così:

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

Questa tecnica può essere correlata a qualsiasi tipo di evento AS3 su cui è possibile utilizzare addEventListener.

E ora puoi aggiungerlo in questo modo:

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) può essere utilizzato direttamente su addEventListener () , ma è meglio tenerlo in una variabile perché potrai rimuoverlo in seguito lo stesso modo in cui l'hai aggiunto:

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

Il e.currentTarget.someCustomProperty comunemente usato funziona per oggetti dinamici (ad es. MovieClip), ma ti deluderà in qualsiasi altra cosa (ad esempio Sprite), costringendoti a costruire un intero oggetto esteso personalizzato / evento per ogni tipo.

Questa soluzione si occupa di ogni "quotabile" " oggetto ed evento. E questa risposta contiene più dettagli ed esempi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top