. .. : Swf.hu 1.0 archívum : Swf.hu főoldal >>> : .. .




 
 
SEGÉDLETEK

  feltöltve: 1970.01.01 | szerző: ismeretlen | olvasva: alkalommal

 

Eseménykezelés

Az eseménykezelő rendszer mindig is folyamatos változásban volt. Először kerültek bevezetésre az objektumokra írható események, majd jöttek a dinamikusan is hozzáadható on... kezdetűek majd megjelentek az esemény figyelők amik listener objektumok segítségével akár egyszerre több eseményt is tudtak figyelni. Az AS3-ban használt eseményfigyelő rendszerre a legjobban az AS2-es komponensek eseménykezelő rendszere hasonlít.

Eseménykezelés alapjai

AS3-ban minden figyelő hozzáadása egy addEventListener nevű metódussal történik azokhoz az objektumokhoz, amelyek képesek eseményeket dobni. Azt hogy milyen eseményt akarunk figyelni egy String segítségével adhatjuk meg a függvénynek. Egy esemény keletkezésekor mindig létrejön egy esemény objektum aminek típusa az Event osztály vagy belőle származó osztályok lehetnek. Ez az event objektum mindig átadódik a figyelő függvénynek és tartalmazza az esemény származásának a helyét target néven. Az Event osztály definiál pár konstans értéket amik az alap események neveit tartalmazzák.

Adjunk hozzá egy figyelőt az enterFrame eseményhez a root-on.

this.addEventListener(Event.ENTER_FRAME, onEnterFrame)

function onEnterFrame(event:Event):void{
      trace("Enter Frame")
}

Elemezzük ezt a pár sort. Az addEventListener adja hozzá a figyelő függvényt amit a 2. paraméterként adtam át. Az első paraméter egy String az esemény neve ami ebben az esetben az "enterFrame" tehát akár ezt is írhattam volna:

this.addEventListener("enterFrame", onEnterFrame)

function onEnterFrame(event:Event):void{
      trace("Enter Frame")
}

Az eseménykezelő függvények mindig egy paramétert kapnak, ami egy event objektum. Ennek az objektumnak a típusa változhat attól függően hogy milyen eseményt figyelünk azonban mindig megtalálható rajta pár fontos információt tároló változó. Ezeket az Event osztály definiálja de esetenként bővülhet az esemény típusától függően. Nézzünk pár fontosabbat.


info  target

Ez a változó tárolja annak az objektumnak a referenciáját ahonnan az esemény származik. A viselkedése hasonlít az AS2-es this viselkedéséhez az eseménykezelő függvényeken belül.


info  currentTarget

Az az objektum amihez az figyelőnket hozzáadtuk.


info  bubbles

AS3-ban az új eseménykezelő rendszernek köszönhetően az események végig vándorolnak a display listán, így lehetőség van akár egy display objektumszülőjén figyelni az általa generált eseményt de erről még később lesz szó. A bubbles azt tárolja hogy így viselkedik-e az esemény.


info  eventPhase

Azt adja meg hogy az esemény épen milyen fázisban van.

info  cancelable

Azt adja meg hogy megállítható e az esemény bekövetkezte.

info  type

Az esemény neve amit éppen figyelünk.

Készítsünk egy gombot és írassuk ki a fenti adatokat.

//Meghívjuk a gomb rajzoló függvényt
var myButton:Sprite = createButton()
//Hozzáadjuk a katintás figyelőjét
myButton.addEventListener(MouseEvent.CLICK,onMouseClick)
//Hozzáadjuk a display listához
this.addChild(myButton)

function onMouseClick(event:MouseEvent):void{
      trace("target: ",event.target)
      trace("currentTarget: ",event.currentTarget)
      trace("type: ",event.type)
      trace("eventPhase: ",event.eventPhase)
      trace("cancelable: ",event.cancelable)
      trace("bubbles: ",event.bubbles)
}

function createButton():Sprite{
     var button:Sprite = new Sprite()
     button.graphics.beginFill(0x3C80C4)
     button.graphics.drawRect(10,10,150,100)
     button.graphics.endFill()
     button.buttonMode = true
     return button
}

Eredmény:
--------------------------
target: [object Sprite]
currentTarget: [object Sprite]
type: click
eventPhase: 2
cancelable: false
bubbles: true
--------------------------

Ebben a mintában a MouseEvent osztályban definiált CLICK eseményhez adtunk figyelőt. Általában ide tartoznak az egér eseményei de nem minden objektum tud minden ezekben az osztályokban megtalálható eseményt dobni. Ahhoz hogy kiderítsük egy objektumhoz milyen események figyelőit lehet hozzáadni meg kell keresnünk a súgóban hogy a típusánál milyen események vannak felsorolva.

Ha azt szeretnénk, hogy a gombunk úgy viselkedjen mint egy gomb vagyis hogy átváltozzon a kurzor kéz alakúvá be kell állítanunk a buttonMode tulajdonságát ahogy ez a fenti kódban is látszik. Ha nincs erre szükségünk akár ki is hagyhatjuk ezt a lépést.

Ha nem szeretnénk tovább figyelni egy eseményt, akkor el kell távolítanunk a figyelőt az esemény nevének és a figyelő függvény átadásával a removeEventListener metódusnak. Távolítsuk el az enterFrame figyelőt 10 lefutás után:

var count:uint = 0
this.addEventListener(Event.ENTER_FRAME, onEnterFrame)

function onEnterFrame(event:Event):void {
      if(count++ == 10){
            this.removeEventListener(Event.ENTER_FRAME, onEnterFrame)
            trace("Removed")
      }else{
            trace("Enter Frame "+count)
      }
}

Lehetőség van akár a függvény vagy a figyelendő esemény nevének tudta nélkül is eltávolítani egy figyelőt az esemény objektum által tárolt adatok alapján:

var count:uint = 0
this.addEventListener(Event.ENTER_FRAME, onEnterFrame)

function onEnterFrame(event:Event):void {
      if(count++ == 10){
            event.currentTarget.removeEventListener(event.type, arguments.callee)
            trace("Removed")
      }else{
            trace("Enter Frame "+count)
      }
}

Az esemény folyam

Amikor egy esemény bekövetkezik a Flash Player elindít egy esemény objektumot. Ezek az objektumok képesek végigmenni a display listán (bubbles) ha az objektum, ami generálta őket hozzá van csatlakoztatva. Ha nincs akkor magán az objektumon keletkezik az esemény így csak magához az objektumhoz adott figyelőkkel lehet azt elkapni.
Vegyük az alábbi ábrát. A Stage áll a display lista csúcsán és belőle ágaznak szét a gyermek objektumai tehát minden látható display objektum kapcsolatban van ezen a módon a Stage-el.

displayHierarchy

A display listán közlekedni képes események 3 fázisban képesek figyelőket értesíteni.
Az első fázisban (capture phase) elindul az esemény a Stage felől ahhoz az objektumhoz ami kiváltotta azt, az alsó mintán ez a "Child 1 Node" nevű objektum. A második fázis (target phase) amikor elér a cél objektumhoz és az ahhoz adott figyelőket értesíti az eseményről. A harmadik fázisban (bubbling phase) vissza indul a Stage felé és értesíti az útba eső figyelőket ha vannak. A jelenlegi fázis számát az eventPhase tárolja az esemény objektumon.

stageEventFlow

 

Alap esetben a figyelők csak a 2. és a 3. fázisban figyelik az események bekövetkeztét. Ahhoz hogy az első fázishoz is tudjunk figyelőt adni használnunk kell az addEventListener egyik opcionális paraméterét a useCapture paramétert ami alap esetben false.

Írassuk ki a fent látott ábra szerint, hogy éppen hol tart az eseményünk.

//Elkészítjük a gombunkat tartalmazó Sprite-ot
var parentNode:Sprite = new Sprite()
parentNode.name = "Parent Node"

//Elkészítjük a gombunkat
var childNode1:Sprite = createButton()
childNode1.name = "Child1 Node"

//Hozzáadjuk a gombot a parentNode-hoz
parentNode.addChild(childNode1)
//Hozzáadjuk a gombot tartalmazó Sprite-ot a root-hoz
addChild(parentNode)

//Hozzáadjuk az útbaeső figyelőket
childNode1.addEventListener(MouseEvent.CLICK,onMouseClick)
parentNode.addEventListener(MouseEvent.CLICK,onMouseClick)
parentNode.addEventListener(MouseEvent.CLICK,onMouseClick,true)
root.addEventListener(MouseEvent.CLICK,onMouseClick)
root.addEventListener(MouseEvent.CLICK,onMouseClick,true)
stage.addEventListener(MouseEvent.CLICK,onMouseClick)
stage.addEventListener(MouseEvent.CLICK,onMouseClick,true)

function onMouseClick(event:MouseEvent):void{
      switch(event.eventPhase){
            case EventPhase.CAPTURING_PHASE:
                  trace("CAPTURING_PHASE")
             break   
             case EventPhase.AT_TARGET:
                  trace("AT_TARGET")
             break 
             case EventPhase.BUBBLING_PHASE:
                   trace("BUBBLING_PHASE")
             break  
      }
      trace(event.currentTarget)
      trace(event.currentTarget.name)
      trace("---------------------")
}

function createButton():Sprite{
     var button:Sprite = new Sprite()
     button.graphics.beginFill(0x3C80C4)
     button.graphics.drawRect(10,10,150,100)
     button.graphics.endFill()
     button.buttonMode = true
     return button
}

Eredmény:
--------------------------
CAPTURING_PHASE
[object Stage]
null
---------------------
CAPTURING_PHASE
[object MainTimeline]
root1
---------------------
CAPTURING_PHASE
[object Sprite]
Parent Node
---------------------
AT_TARGET
[object Sprite]
Child1 Node
---------------------
BUBBLING_PHASE
[object Sprite]
Parent Node
---------------------
BUBBLING_PHASE
[object MainTimeline]
root1
---------------------
BUBBLING_PHASE
[object Stage]
null
---------------------

Ebből a kis mintából is lehet látni, ahogyan egy esemény objektum mozog a display listán. Először a Stage-től az eseményt kiváltó objektumig majd vissza. Látszik hogy milyen könnyű ennek a módszernek a segítségével például menüket csinálni ugyanis csak a menügombokat tartalmazó objektumon kell figyelnünk az egér eseményeit és egy függvény segítségével be tudjuk állítani több gomb állapotát is az egértől függően.

Paraméter átadás

Mivel sokan kérdezték már különböző fórumokon, hogy miként lehetne tetszőleges paramétereket is átadni az esemény objektumon kívül, ezért most bemutatok egy ilyen megoldást. Az egyik egy másik függvény használata, ami majd átadja az általunk definiált paramétereket az esemény figyelő függvénynek:

this.addEventListener(Event.ENTER_FRAME,argsFunc(enterFrame,"hello",12));

function enterFrame(event:Event,greet:String,num:Number):void {
     trace(greet,num);
}

/*********************************************************/
function argsFunc(func:Function,... args):Function {
     var myFunc:Function = function(event:Event):void{
          var pasArgs:Array = args.concat()
          pasArgs.unshift(event)
          func.apply(this,pasArgs)
     };
     return myFunc;
}

Ha az argsFunc-ot használjuk tetszőleges paraméter átadásra, akkor az első paramétereknek a figyelő függvénynek kell lennie, majd jöhetnek a tetszőleges értékek. Ebben az esetben, a figyelő függvényben is definiáljuk az átadott paramétereket az esemény objektumon felül.
Ha törölni is szeretnénk a figyelőt, akkor egy másik függvényt kell használnunk ami átadja a törlendő függvény referenciáját is. Töröljük az enterFrame eseményt egy lefutás után az argsFunc2 segítségével:

this.addEventListener(Event.ENTER_FRAME,argsFunc2(enterFrame,"hi",36));

function enterFrame(event:Event,toRemoveFunc:Function,greet:String,num:Number):void {
     trace(greet,num);
     this.removeEventListener(Event.ENTER_FRAME, toRemoveFunc)
}

/*********************************************************/
function argsFunc2(func:Function,... args):Function {
     var myFunc:Function = function(event:Event):void{
          var pasArgs:Array = args.concat()
          pasArgs.unshift(arguments.callee)
          pasArgs.unshift(event)
          func.apply(this,pasArgs)
     };
     return myFunc;
}

A fent leírtak csak lehetséges megoldások a tetszőleges paraméterek átadására, de többnyire minden ilyen probléma megoldható körültekintő tervezéssel. Inkább csak ezért írtam le ezeket, hogy bemutassak egy lehetséges megoldást.

 
 
 

© Devnet.hu. A segédletek semmilyen formában nem másolhatók, publikálhatók a Devnet.hu és a szerzők közös írásos engedélye nélkül.
 
. .. : Swf.hu 1.0 archívum : Swf.hu főoldal >>> : .. .