Az ActionScript egy eseményvezérelt nyelv. A program minden változása egy esemény hatására következik be.
Az esemény bekövetkezésekor egy előre megadott programrészlet lefut. (amelynek hatására, akár újabb események váltódhatnak ki)
1. ActionScript 3.0
1.1. Eseményvezérlés az AS3-ban
ActionScript 3-ban minden esemény egy objektum, amely az Event osztály vagy annak egy alosztályának példánya. Az esemény objektum nem csak az esemény részletes leírását, de az annak kezeléséhez szükséges metódusokat is tartalmazza.
Minden esemény három részből áll:
- az esemény forrása (source, más néven event target): melyik objektum fogja kiváltani.
- maga az esemény (event): mi történik pontosan
- a válasz (response): milyen műveletet hajtsunk végre
Gyakorlatban a target egy objektum, az esemény egy esemény objektum, a válasz pedig egy metódus szokott lenni.
Objektumhoz eseményt rendelni egy figyelő (listener) segítségével lehet az addEventListener függvénnyel, mely paraméterként az eseményt és a végrehajtandó függvényt mint objektumot kapja.
A figyelő egy olyan speciális objektum vagy függvény, amely bejegyzi magát egy másik objektumhoz, hogy értesülni szeretne, ha azon valamely esemény megtörténik.
function eseményVálaszFüggvény(eseményObjektum:EseményTípus):void {
// Végrehajtandó kód
}
eseményForrás.addEventListener(EseményTípus.ESEMÉNY_NEVE, eseményVálaszFüggvény);
Lássuk, mi történik ilyenkor a háttérben:
Legyen a konkrét eseményünk a MouseEvent eseményosztály CLICK eseménye (az egér bal gombjával való kattintás). Amikor a Flash Player megnyitja a fájlt, feljegyzi, hogy van egy eseményVálaszFüggvény nevű függvény. Amikor a fenti kód lefut, az eseményForrás objektum figyelői közé bekerül egy referencia az eseményVálaszFüggvény-re Amikor valaki rákattint az eseményForrás objektumra, a Flash Player létrehoz egy MouseEvent objektumot, ami leírja az esemény részleteit: miféle esemény, hol, milyen objektummal történt. Ezután a Flash Player végignézi az eseményForrás figyelőit, és meghívja őket, a MouseEvent objektumot átadva nekik.
1.2. Különbség a korábbi verziókhoz képest
A leglényegesebb eltérés a korábbi AS verziókhoz képest az az eseménykezelésben, hogy bár még az AS2-ben is ötféle különböző eseménykezelő rendszer volt, az AS3-ban ezeket egyesítették és egységesítették. Ez az ötféle eseménykezelő rendszer a következő:
- on() események és onClipEvent() események, melyek közvetlenül MovieClip és Button objektumokhoz rendelhetőek hozzá.
- callback események: egy objektum egy eseményéhez lehet egy függvényt csatolni (pl. az XML.onload)
- eseményfigyelők
- UIEventDispatcher osztály a DOM eseménymodell részleges implementációjára
Ezeknek mint megvolt a maga előnye és hátránya, például az on és onClipEvent események könnyen, gyorsan használhatóak voltak, de egy nagyobb projektnél nem volt célszerű, hogy a kódrészletek közvetlenül a MovieClipekbe voltak rakva, nehéz volt őket megtalálni.
A callback függvényeket is könnyű volt használni, de nagy hátrányuk volt, hogy így egy eseményhez nem lehetett, csak egyetlen függvényt hozzárendelni (ez persze kikerülhető volt, de ennek ellenére problémás).
Ráadásul az öt különböző modell nem csak a fejlesztők számára volt problémás, hanem a felhasználóknak is, mert az öt modellnek sem a szintaxisa sem a szemantikája nem egyezett meg mindenhol teljesen egymással. A this kulcsszó például mást és mást jelentett.
Az AS3 ezzel szemben egy új, egységes modellt vezetett be, a DOM eseménykezelő modelljére alapozva. Bár az SWF fájl szerkezete nem teljesen azonos a DOM-éval, a megjelenítési lista (display list) és a DOM között elegendő hasonlóság van technikailag a megfeleltetésre (azaz a display objektumok és a node-ok közötti megfeleltetésre). A DOM modell a viselkedés (behaviour) fogalmára épül.
1.3. Eseményfolyam (event flow)
Ennek a résznek a megértéséhez szükséges lehet a display list ismerete.
Amikor egy esemény bekövetkezik, a Flash Player elküldi a generált esemény objektumot. Amennyiben az érintett objektum (a forrás, azaz célobjektum (target)) nincs a display listben, rögtön ennek továbbítja az eseményt. Amennyiben azonban a target a display list része, a display listnek kerül elküldésre az esemény, és azon továbbítódik a cél felé. Az eseményfolyam, azaz event flow azt írja le, hogy az esemény milyen útvonalon jut el a célobjektumhoz. Az eseményfolyam három részből áll:
- capture phase ("zsákmány-fázis") - az az út, amelyet a cél felé teszünk a Stage-ből indulva
- target phase (cél-fázis) - magánál a célobjektumnál
- bubbling phase ("buborék-fázis") - az az út, amit visszafelé teszünk a Stage-hez
Ennek célja az, hogy egy eseményt ne csak az azt kiváltó objektumnál, hanem az event flow-ban szereplő node-oknál is le tudjunk kezelni. Például olyankor jó ez, ha egy gomb és egy címke van egy objektumban, és az objektumban szeretnénk lekezelni azt, ha a gombra kattintanak, mert abban történnek a lényegi változások.
Az Event osztálynak van néhány speciális, az event flow szempontjávól lényeges propertyje:
- bubbles - Egy eseményről azt mondjuk, hogy "buborékos", ha a targettől a Stage felé továbbadódik annak szülőin keresztül. Ez az attribútum azt tárolja, hogy az adott esemény ilyen-e
- eventPhase - Tartalmazza, hogy épp melyik fázisban vagyunk. E közül a három konstans közül valamelyik: CAPTURING_PHASE, AT_TARGET, BUBBLING_PHASE
- target - A célobjektumra való referencia
- currentTarget - Az aktuális objektum referenciája
Az Event osztálynak három típusú metódusa van:
- használati metódusok
- clone() - lemásolja az eseményt
- toString() - szöveges formában visszaadja az esemény leírását
- eseményfolyam metódusok - ezekkel az eseményfolyamból vehetünk ki csomópontokat
- alapviselkedés metódusok - események alapértelmezett viselkedését befolyásolhatjuk (tilthatjuk) velük (pl. hogy dupla kattintásnál kijelöljük a kurzor alatt lévő szót)
1.4. Eseményfigyelők (event listener)
Az eseményfigyelők, más néven eseménykezelők olyan speciális függvények, melyek bizonyos események hatására hajtódnak végre. Eseményfigyelő létrehozása általában két lépéses:
- Először szükség van egy konkrét függvényre vagy metódusra, ami ezt a működést megvalósítja, ezt általában először létre kell hozni.
- Az addEventListener() metódussal regisztálni kell a célobjektumnál a figyelőt
Eseményfigyelőket eltávolíthatunk a removeEventListener() függvénnyel, ha már nincs rájuk szükség.
Eseményt kiváltani a dispatchEvent(myEvent:MyEventType) metódussal lehetséges
2. ActionScript 2.0
2.1. Eseményvezérlés
Az ActionScript egy eseményvezérelt nyelv. A program minden változása egy esemény hatására következik be.
Az esemény bekövetkezésekor egy előre megadott programrészlet lefut. (amelynek hatására, akár újabb események váltódhatnak ki)
JavaScripttel ellentétben nincs Event, azaz eseményt leíró objektum.
A régebbi Flash 5 és a jelenlegi Falsh MX között a eseményvezérlés szintaktikájában is jelentős fejlődés történt. Ez pedig a callback függvények
használata. Pl. az előző verzióban egy gomb megnyomásánál a következő kódrészletnek a gombhoz tartozó résznél kellett lennie: on(Press){utasítások}. (Ha
a gomb megnyomódik, akkor lefutnak az utasítások.)
Az új verziónál lehetőség van arra, hogy ne kelljen minden eseményvezérlést máshol tárolnunk, ezáltal bármikor lehet módosítani az eseménykezelők
felüldefiniálásával a gomb viselkedését. gomb_neve.onPress=function(){utasítások}
Tehát a szintaktika: objektum.eseményleíró = callbackfüggvény
A Flash MX eseménykezelő-modelljével ismerkedjünk meg részletesebben
Mint feljebb említettük, nagy fejlődést mutat ez a Flash 5 lehetőségeihez képest, szépen felépített és jól áttekinthető, ugyanakkor moduláris és könnyen
variálható scripteket írhatunk. Ezekkel egyszerűbben és sokrétűben hozhatunk létre animációkat, ötletes és hasznos interaktív elemeket.
Az alapvető meghatározások mellett néhány trükköt is bemutatunk.
Már említettük, hogy az ActionScript egy eseményvezérelt nyelv, ezért elsőként az esemény (event) fogalmát kell tisztáznunk. Eseménynek nevezzük azt a
dolgot, ami a mozi futása közben történik. Ez lehet a felhasználó által generált esemény, mint pl. egy egérkattintás vagy egy billentyű lenyomása, ill.
lehet rendszeresemény, amire jó példa az, hogy a mozi egy képkockáról a következőre lép.
Többféle lehetőségünk van események kezelésére:
- Eseménykezelő metódusok (event handler methods) használata
- Eseményfigyelők (event listeners) használata
- Egy filmklip vagy nyomógomb speciális eseménykezelőinek használata
- Komponensek eseménykezelése
2.2. Eseménykezelő metódusok használata
Az eseménykezelő valójában egy függvény, ami akkor hajtódik végre, amikor az adott esemény bekövetkezik. Eseménykezelő pl. az onEnterFrame vagy az
onMouseMove, ez azonban nem csinál semmit addig, amíg nem definiálunk egy függvényt, amit végrehajthat (addig undefined az értéke). Itt fontos
megjegyeznünk, hogy valójában az enterFrame esemény következik be, és az onEnterFrame, ill. az ahhoz kapcsolt függvény az, amivel megmondjuk, hogy mi
történjen. Azt, hogy enterFrame, Flash MX-ben nem írjuk a scriptbe soha, csak azért használjuk így, hogy tudjunk beszélni róla.
A következő ActionScript osztályok definiálnak eseménykezelőket: "Button osztály", "ContextMenu osztály", "ContextMenuItem osztály", "Key osztály",
"LoadVars osztály", "LocalConnection osztály", "Mouse osztály", "MovieClip osztály", "MovieClipLoader osztály", "Selection osztály", "SharedObject
osztály", "Sound osztály", "Stage osztály", "TextField osztály", "XML osztály", és "XMLSocket osztály".
Egy eseménykezelő három fő részből áll: egy objektumból, amin az esemény kiváltódik; az objektumhoz tartozó eseménykezelő metódus nevéből; és az
eseménykezelőt megvalósító függvényből. A következő kód jelzi az eseménykezelők alapvető struktúráját:
object.eventMethod = function () {
// Az eseménynek megfelelő kód
}
illetve Flash MX-ben:
function fvname() {
// Az eseménynek megfelelő kód
}
majd:
object.eventMethod = fvname;
Flash 5 stílusban, ha egy moziklipet mozgatni akarunk, a legkézenfekvőbb megoldásnak az bizonyul, ha kihúzunk egy példányt a színpadra, és arra ráírjuk
pl. a következőt:
onClipEvent(enterFrame) {
_x+=Math.round(Math.random()*5);
}
A fenti kód az enterFrame esemény érzékelésének köszönhetően másodpercenként annyiszor lefut, amennyi az fps-nél beállított érték. Ez alapértelmezés
szerint 12, de a 24-25 az ideális, mert már a folyamatosság látszatát kelti, de még nem gazdálkodik túl pazarlóan egy átlagos gép erőforrásaival (most
állítsuk 25-re). Tehát az eredmény az, hogy a moziklipünk 0 és 5 közötti véletlenszerű egész értékekkel jobbra mozdul, egyfajta egyenetlen sebességű,
egyirányú mozgást produkálva. Tegyük fel, hogy 15 golyóbist szeretnénk így mozgatni. Így mindegyikre rá kell ezt a kódot másolni. Ez egyrészt felesleges
időpocsékolás, másrészt, ha egy apró kiegészítést szeretnénk a viselkedésükben (pl. az _y tulajdonságot is növelni akarjuk), mindenhol át kell írni a
sorokat, ami az időt és az átláthatóságot tekintve sem optimális megoldás. Ehelyett egy más megközelítést alkalmazunk. Hozzunk létre egy új mozit, ebben
egy script és egy golyok nevű réteget a fő idősíkon (_root), nevezzük el a golyobis moziklip egy példányát golyobis_mc-nek a golyok rétegen, és írjuk a
script réteg egyetlen frame-jére a következőket:
function mozgas () {
this._x+=Math.round(Math.random()*5);
}
stop();
golyobis_mc.onEnterFrame=mozgas;
Az első, amire rá kell mutatnunk, a this szerepe. Ha egy változót, tulajdonságot, szimbólum példánynevet elérési út nélkül adunk meg (pl. _x vagy
golyobis_mc), az az adott idősíkra fog vonatkozni, esetünkben ez a _root-ot jelentené. A this használatával viszont a hatókört a meghívó objektumra, itt
éppen a golyobis_mc-re helyezzük át. Direkt meghívással (mozgas() vagy _root.mozgas()) a teljes fő idősík mozdulna, de így, hogy a golyobis_mc
onEnterFrame eseménykezelőjéhez rendelve hívódik meg, csak a golyobis_mc mozdul.
A másik dolog, hogy attól még, hogy a stop()-pal leállítottuk a fő idősíkot, és valójában nem ugrunk a következő frame-re, (főleg, ha csak egy frame-ből
áll a mozi), az onEnterFrame-hez csatolt függvény még továbbra is folyamatosan lefut az fps-nek megfelelő gyakorisággal.
A harmadik, és egyben a legfontosabb említendő momentum az eseménykezelő metódus definiálása. Amikor egy névvel ellátott függvényt hozunk létre, maga a
név mutat a memóriában létrehozott utasításhalmazra. Ezt a hivatkozást egy másik változónak – pl. masikMozgas=mozgas -, vagy akár a fent látott módon egy
eseménykezelőnek is átadhatjuk. Vigyáznunk kell viszont arra, hogy ekkor zárójelek nélkül kell a függvénynevet használnunk, mert a zárójelpár
mindenképpen meghívást jelent.
// az onEnterFrame a mozgas fv. visszatérési értékét veszi fel – helytelen módszer
golyobis_mc.onEnterFrame=mozgas();
// az onEnterFrame magára a mozgas fv.-re mutat
golyobis_mc.onEnterFrame=mozgas;
Tegyünk egy próbát! Az alábbi esetben a mozgas függvény mindössze egyszer hívódik meg, a visszatérési érték a golyobis _x tulajdonsága, amit a trace
paranccsal kiíratunk az Output ablakba, mint a golyobis_mc.onEnterFrame értékét. Ennek pedig nem sok értelme van, azon felül, hogy nem is működik a
mozgás, amit látni szeretnénk. Ha viszont az utolsó előtti sorból a zárójelpárt levesszük, rendesen működik az animáció, a trace pedig immár helyesen
type Function-t ír ki, mivel az onEnterFrame-hez függvényt rendeltünk.
function mozgas () {
this._x+=Math.round(Math.random()*5);
return this._x;
}
stop();
golyobis_mc.onEnterFrame=mozgas();
trace(golyobis_mc.onEnterFrame);
Ezzel azonban még nem vagyunk készen, ugyanis csak egy golyóbist mozgattunk. 15 példányt a színpadra kihúzva, és azokat a azokat a golyobis_mc,
golyobis1_mc, stb. sorozatként golyobis14_mc-ig elnevezve a következő egyszerű, rövid ciklussal az összes moziklipet irányíthatjuk.
function mozgas () {
this._x+=Math.round(Math.random()*5);
}
stop();
for (i=0; i<15; i++) {
_root[’’golyobis”+i+”_mc”].onEnterFrame=mozgas;
}
Itt azt használjuk ki, hogy különböző objektumokat, szimbólumok példányait, azok tulajdonságait, metódusait el lehet érni a tömbjelölés segítségével is,
ahol a nevet sztringként alkalmazzuk. _root[’’golyobis’’+6+”_mc”] ugyanazt jelenti, mint _root.golyobis6_mc.
Ezen kívül még létezik egy másik lehetőség is, ami adott esetben még hasznosabb lehet, mivel a for ciklusra nincs szükség, és még a sorozatos
elnevezéssel sem kell bíbelődni, bár a nevek használatának nélkülözése a későbbi, ill. futásidejű változásokat nem könnyíti meg.
Töröljünk le minden moziklippéldányt a Stage-ről, a _root-on pedig csak a mozgas függvénydeklarációt és a stop()-ot hagyjuk. Magában a golyobis
Library-elemben a scriptnek hozzunk létre egy – a szokásos módon script nevű – külön réteget, ennek egyetlen frame-jére pedig a következőt írjuk:
stop();
onEnterFrame=_root.mozgas;
Ettől kezdve az összes színpadra kihúzott példány lassan áthalad a képernyőn, mindegyik a saját véletlenszerű sebességváltozásainak megfelelő módon.
Ha azt szeretnénk, hogy mondjuk az x tengelyen 300 pixelnél megálljanak a golyóbisok, lehet a mozgas függvénybe egy olyan feltételt tenni, ami ha 300-nál
nagyobb lenne az _x, akkor az maradjon 300-on. Ekkor azonban az onEnterFrame még azután is fut, hogy már nincs rá szükség, mert a golyó áll. Ha a mozi
futása során még sok onEnterFrame-et használunk, és egyiket sem állítjuk le, miután elvégezte a dolgát, előbb-utóbb irgalmatlanul belassul a lejátszás. A
feleslegesen futó metódust érdemes ilyenkor lekapcsolni az eseménykezelőről. Tegyük a golyóbisokat 300-nál kisebb x-pozícióba, és írjuk át a mozgas
függvényt a következők szerint:
function mozgas () {
this._x+=Math.round(Math.random()*5);
if (this._x>=300) {
this._x=300;
this.onEnterFrame=undefined;
}
}
A this.onEnterFrame=undefined ugyanazt eredményezi, mint a delete this.onEnterFrame, jóformán ízlés kérdése, hogy melyiket használjuk. Ezen utasítások
nem szüntetik meg a mozgas függvényt, csupán innentől kezdve az nincs hozzárendelve az eseménykezelőhöz. Amennyiben a későbbiek során újra mozgatni
akarjuk valamelyik golyóbisunkat, elég újra a golyobis1_mc.onEnterFrame=mozgas formát használni, miután az egyik moziklipünket golyobis1_mc-nek neveztük
el. Máris halad tovább a moziklip, amennyiben valahogy visszatettük előtte 300-nál kisebb x-pozícióba. Erre megoldásként kínálkozik a következő példa,
mely rögvest az eseménykezelők hozzárendelésének egy másik módját is bemutatja. A _root-on lévő script végére tegyük a következőket:
onMouseDown=function () {
golyobis1_mc._x=150;
golyobis1_mc.onEnterFrame=mozgas;
};
Előbb visszahelyeztük a moziklipet, majd mozgásra bírtuk, és mindezek megtörténtét egy egérkattintáshoz kötöttük. Ami újszerű, az az, hogy itt
közvetlenül az eseménykezelőhöz (onMousDown) rendeltünk egy névtelen függvényt. Ezt a rövidebb módszert akkor érdemes használni, amikor tudjuk, hogy a
függvényt csak egyszer akarjuk az adott kezelőhöz kapcsolni. Ha ugyanis egyszer – pl. az undefined alkalmazásával – leválasztottuk az eseménykezelőről,
később már – név hiányában – nem tudunk rá sehogy hivatkozni.
Ezt a formát kell akkor is követnünk, amikor az eseménykezelőhöz tartozó függvénynek paramétereket kívánunk átadni. Az eddigi példánál maradva, immár
paraméterekkel szeretnénk megmondani, hogy meddig menjen a golyóbis. Az onMousDown-t és a hozzá tartozó névtelen függvényt töröljük ki a _root-ról, a
mozgas függvényt pedig írjuk át az alábbiaknak megfelelően:
function mozgas (klip, hatar) {
klip._x+=Math.round(random()*5);
if (klip._x>=hatar) {
klip._x=hatar;
klip.onEnterFrame=undefined;
}
}
A golyobis Library-elemben található onEnterFrame-et a következőképpen fogalmazzuk át:
onEnterFrame=function () {
_root.mozgas(this, 200);
};
A mozgás függvényt kibővítettük két paraméterrel, a klip az adott moziklipre fog vonatkozni, a határ pedig, azt hiszem, nem szorul magyarázatra. Az
onEnterFrame-hez közvetlenül nem használhatjuk az onEnterFrame=_root.mozgas(this, 200) formát, mivel ugyebár a zárójelek miatt a mozgás rögtön meghívásra
kerülne és csak egyszer, helytelen működést eredményezve. Így tehát egy névtelen függvénybe kell csomagolnunk a mozgas meghívását. Mivel már nem
követlenül az eseménykezelőhöz kapcsoltuk azt, hanem direkt módon meghívtuk, ha a mozgas-ban nem lenne klip paraméter, és a thiseket meghagytuk volna, a
teljes fő idősík mozdulna el, mivel a this ez esetben arra mutatna. Így szükséges bevezetnünk egy paramétert, hogy megmondjuk, mire vonatkozzon a
mozdítás. A golyobis-ban a _root.mozgas(this, 200)-ban szereplő this mindegyik golyobis-példány saját idősíkját jelenti, így megoldottuk a feladatot.
Ugyanúgy, ahogy először hozzákapcsoltunk valamilyen függvényt egy eseménykezelőhöz, majd leválasztottuk róla, természetesen nem csak ugyanazt
rendelhetjük hozzá újra, hanem akármilyen másik függvényt is. Ki is próbálhatjuk, például írjunk egy újabb függvényt a mozgas elé, ami a mozgás
végeztével triplájára növeli a golyóbisunkat:
function noveles () {
this._xscale=this._yscale+=10;
if (this._xsale>=300) {
this._xscale=this._yscale=300;
this.onEnterFrame=undefined;
}
}
A mozgas függvényben csak a következőt kell változtatni:
klip.onEnterFrame=noveles
Egy ActionScript 2.0 osztályból származtatott osztályban felüldefiniálhatjuk az öröklött eseménykezelő metódusokat. A következő példában felüldefiniáljuk
a MovieClip osztály onPress eseménykezelőjét, ami következtében, ha rákattintunk a származtatott osztály bármely példányára, akkor jobbra mozdul el 20
pixelt.
// MoveRight osztály
class MoveRight extends MovieClip {
function onPress() {
this._x += 20;
}
}
2.3. Eseményfigyelők használata
A mozinkban elhelyezett objektumok figyelhetik az eseményeket, és reagálhatnak is rájuk. Ezek az eseményfigyelők (listener). Nem mindenféle objektum
figyel minden eseményre, valamelyikhez nekünk kell hozzárendelni azt. Ilyen pl. a moziklip objektum: figyel az egéreseményekre, de a
billentyűzetfigyelésre már utólag kell rábírnunk.
Az eseményfigyelők két részből állnak: egy figyelő objektumból (listener object), ami reagál egy eseményre és egy adó objektumból (broadcaster object),
ami regisztrálja a figyelő objektumot és megadja neki, hogy fogadja az eseményt. Például regisztrálhatunk egy nyomógomb objektumot, hogy fogadja egy
szövegdoboz megváltoztatására irányuló eseményeket. Hozzákapcsolhatunk több figyelő objektumot is egyetlen adó objektumhoz, és egy figyelő objektum
számos adó objektumtól fogadhat eseményeket.
A következő ActionScript osztályok képesek eseményfigyelők használatára: "Key osztály", "Mouse osztály", "MovieClipLoader osztály", "Selection osztály",
"Stage osztály", and "TextField osztály".
Az eseményfigyelők eseménykezelő modellje hasonlít a fenti eseménykezelő metódusok használatára, két fő különbséggel:
- Az eseménykezelő a figyelő objektumhoz van hozzákapcsolva, és nem ahhoz az objektumhoz, ami közvetíti az eseményt.
- Az adó objektumnak van egy speciális metódusa (addListener()), ami regisztrálja a figyelő objektumo(ka)t, akik majd fogadják az ő eseményeit.
A következő kód bemutatja az eseményfigyelők működését:
var listenerObject.eventName = function(){
// Eseménykezelő kód helye
};
broadcasterObject.addListener(listenerObject);
A fenti kód némi magyarázatra szorul. A kód egy figyelő objektummal (listenerObject) és annak egy tulajdonságával kezdődik (eventName). A figyelő
objektum egyrészt a színtéren lévő bármelyik filmklip vagy gomb objektum lehet, másrészt lehet egy ActionScript osztály példánya is.
A figyelő objektumhoz hozzárendelünk egy függvényt, ami kezeli az eseményt.
Végül meg kell hívni az adó objektum addListener() metódusát, paraméterként megadva a figyelő objektum nevét, és ezzel összekapcsoltuk a két objektumot.
Ahhoz, hogy töröljünk egy már bejegyzett figyelő objektumot, meg kell hívni az adó objektum removeListener() metódusát, a törölni kívánt figyelő objektum
nevével paraméterezve:
broadcasterObject.removeListener(listenerObject);
A következő példa szemlélteti, hogy hogyan alkalmazhatunk figyelő objektumot a gyakorlatban. A konkrét példában a Selection osztály onSetFocus figyelő
objektuma segítségével létrehozzuk szövegdobozok egy egyszerű fókusz kezelőjét (focus manager).
A fókuszban lévő szövegdoboz kerete megjelenik és a másik szövegdoboz (ami nincs fókuszban) kerete eltűnik:
// Létrehozunk egy új figyelő objektumot, focusListener néven
var focusListener:Object = new Object();
// Definiáljuk a figyelő objektumhoz tartozó függvényt
focusListener.onSetFocus = function(oldFocus_txt:TextField, newFocus_txt:TextField) {
oldFocus_txt.border = false;
newFocus_txt.border = true;
}
// Összekapcsoljuk a figyelő objektumot az adó objektummal
Selection.addListener(focusListener);
2.4. Egy filmklip vagy nyomógomb speciális eseménykezelőinek használata
A színtéren lévő nyomógomb, illetve filmklip példányokhoz közvetlenül is hozzákapcsolhatunk eseménykezelőket. Nevezetesen az on() és onClipEvent()
eseménykezelőket használhatjuk, és ekkor a nyomógomb, illetve filmklip példányokra kell „ráírnunk” a kódot. Nem használhatjuk eseménykezelésre ezt a
lehetőséget, olyan nyomógomb, illetve filmklip példányok esetében, amiket futási időben hozunk létre, ilyen esetekben az előző két eseménykezelő módszer
használható.
Az on() eseménykezelő gombesemények kezelésére alkalmas, és a következő szintaxissal használhatjuk:
on(mouseEvent) {
// A kód helye
}
AmouseEvent paraméter lehetséges értékei (, és az események leírása):
press: Az egér gombja nyomva van, mialatt az egér kurzor a nyomógomb fölött van.
release: Az egér gombját felengedjük, mialatt az egérmutató a nyomógomb fölött van.
releaseOutside: Mialatt az egérmutató a nyomógomb fölött van, lenyomjuk az egér gombját, majd a nyomógomb területén kívül engedjük fel. A press és a
dragOut események mindig megelőzik a releaseOutside eseményt.
rollOut: Az egérmutató kikerül a nyomógomb területéről.
rollOver: Az egérmutatóval áthaladunk a nyomógomb területe felett.
dragOut: Az egérmutatóval a nyomógomb területe felett állunk és lenyomjuk az egér jobb gombját, nyomva tartjuk, majd kigördítjük a nyomógomb
területéről az egérmutatót.
dragOver: Az egérmutatóval a nyomógomb területe felett állunk és lenyomjuk az egér jobb gombját, kigördítjük a nyomógomb területéről az
egérmutatót, majd visszagördítjük a nyomógomb fölé.
keyPress ("key"): Meghatározott billentyű leütése. A paraméter kulcs része ("key") egy billentyű kód vagy billentyű konstans lehet. Jól használható ez a
lehetőség arra, hogy bizonyos előre definiált billentyűk viselkedését felülírjuk. A nyomógomb elhelyezhető az alkalmazás bármely pontján, a színtéren
belül, illetve kívül is. Az egyetlen korlátja ennek a technikának, hogy az on() eseménykezelő nem alkalmazható futási időben.
A fentiek szemléltetésére tekintsük a következő két példát:
on(press) {
trace("Megnyomtad a gombot!");
}
Több esemény is „lekezelhetünk” ugyanazon on() eseménykezelő használatával, ha az egyes eseményeket vesszővel elválasztva soroljuk fel:
on(rollOver, rollOut) {
trace("Áthaladtál felettem vagy legördültél rólam!");
}
Az
onClipEvent() eseménykezelő filmklip események kezelésére alkalmas, a következő formában:
onClipEvent(movieEvent){
// A kód helye
}
A movieEvent paraméter lehetséges értékei (, az események leírása megtalálható a Típusok fejezetben a MoviClip típus eseménykezelőinek leírásánál):
load, unload, enterFrame, mouseMove, mouseDown, mouseUp, keyDown, keyUp, data
A fentiek szemléltetésére tekintsük a következő példát, ami a keyDown filmklip eseményt „figyeli”, és a Key.getCode() függvény segítségével megállapítja,
hogy a felhasználó melyik billentyűt ütötte le, és ennek megfelelően folytatja az előző vagy a következő képkockán a lejátszást:
onClipEvent (keyDown) {
if (Key.getCode() == Key.RIGHT) {
this._parent.nextFrame();
} else if (Key.getCode() == Key.LEFT) {
this._parent.prevFrame();
}
}
A Flash MX esetében már természetesen a fenti módszer mellett itt is kihasználhatjuk a callback függvény előnyeit!
Érdemes kiemelni az onMouseMove-ot, aminek segítségével könnyedén készíthetünk saját egérmutatót, és egy fontos elvi dologra világítunk rá.
Egy teljesen új, egy frame-ből álló moziban hozzunk létre egy klip és egy script réteget. A klip rétegre egy tetszőleges, egeret helyettesítő moziklipet
tegyünk, aminek legyen eger_mc a neve, a script rétegre pedig írjuk a követezőket:
stop();
Mouse.hide();
eger_mc.onMouseMove=function () {
this._x=xmouse;
this._y=ymouse;
};
A Mouse.hide()-al eltüntetjük az eredeti egeret és ezzel készen is volnánk, de van egy kis bökkenő. Itt ugyanis csak onnantól kezdi az egérmutató helyét
követni a moziklipünk, miután megmozdítjuk egerünket. Próbáljuk ki a Flash MX-ben Ctrl+Enter-rel teszteljük a mozit, de ne mozdítsuk meg az egeret, csak
később. Addig a moziklip a színpadon van a kezdeti pozícióban. Kézenfekvőnek látszik a megoldás, hogy meg kell hívni az onMouseMove-hoz tartozó
függvényt. Csakhogy az egy névtelen függvény, nem tudunk rá hivatkozni a megszokott függvényhívást alkalmazva. Beírni mégegyszer az onMouseMove-ban
szereplő utasításokat, hogy ezek egyszer a mozi kezdetén mindenképpen lefussanak, nem valami professzionális megoldás. Szerencsére az eseménykezelőhöz
kapcsolt függvényt meg tudjuk hívni a következőképpen is:
Írjuk is be a kódunk végére. Ez természetesen itt nem takarít meg sok helyet és munkát, de egy bonyolult, hosszú eseménykezelő metódus esetében ez a
módszer nagyon hasznos lehet. Gondoljunk egy sok gombból álló menüre, mindegyik onRelease-éhez különböző függvények, utasítások tartoznak: ha valahonnan
szeretnénk az egyik menüpontra történő kattintást utánozni tényleges kattintás nélkül, elég csupán a következőt írni:
tesztKlip_mc.onRollOver=function () {
trace(’’mintha a menüpont3_mc-re kattintottunk volna’’);
menupont3_mc.onRelease();
}
Ily módon paramétereket is adhatunk az eseménykezelő metódusnak, ritkán van rá szükség, de jól jöhet.
proba_mc.onRelease=function(par1, par2) {
//függvénytörzs
}
proba_mc.onRelease(’’valami’’, pl_egy_változó);
Egy pár mondat erejéig visszatérve az egérkövető mozikliphez, a függvénytörzs utolsó soraként érdemes beszúrni az updateAfterEvent() utasítást. Ez
annyiszor frissíti a képernyőt, ahányszor csak az adott esemény bekövetkezik. onMouseMove-nál gyakorlatilag nagyon szép folyamatos mozgást
produkálhatunk, akár 1 fps mellett is. Állítsuk ilyen alacsonyra, próbáljuk ki updateAfterEvent()-tel, aztán nélküle is – észrevehető a különbség.
Végezetül nem szabad elmennünk a függvények deklarálásának két módja mellett:
function probaFuggveny () {
}
probaFuggveny=function () {
}
Meghíváskor ugyanúgy a probaFuggveny ()-t használjuk, de az eseménykezelőkhöz rendelésnél vigyázni kell a sorrendre. Ha az első formát alkalmazzuk,
mindegy, hogy a kódban az eseménykezelőhöz a függvénydeklaráció előtt vagy után rendeljük a függvényt, mert a Flash legelőször a függvényeket nézi meg. A
második formánál azonban annak ellenére, hogy itt is függvényről van szó (még ha névtelenről is), egy értékadás jobb oldalán találjuk a functiont, így
ezt már a szekvenciális megközelítésnek köszönhetően mindenképpen az eseménykezelőhöz kapcsolás elé kell írni, ugyanis addig nem létezik a függvény, amíg
a Flash „fentről lefelé” el nem jut odáig az értelmezésben.
2.5. Komponensek eseménykezelése
Minden komponens rendelkezik eseményekkel, amik vagy felhasználói interakciók következtében állnak elő (pl.: click és change események), vagy akkor,
amikor valami meghatározó történik a komponenssel (pl.: load esemény).
(A komponensek áttekintése megtalálható a mellékletben.)
A komponensek eseményeit is a fent említett technikákhoz hasonló módon lehet kezelni, részletesebben csak az eseményfigyelők használatára térek ki.
A legfontosabb jellegzetességek:
- Az adó objektum (broadcaster) maga a komponens példány (componentInstance).
- A figyelő objektum egy függvény vagy egy objektum is lehet.
- A figyelő regisztrálása az addEventListener metódussal történik. A következő szintaxist kövessük:
componentInstance.addEventListener("eventName", listenerObjectORFunction);
- Ha a figyelő egy objektum, akkor egy függvényt kell definiálni a számára, ami lefut az esemény bekövetkezésekor. A szintaxis a következő:
var listenerObject:Object = new Object();
listenerObject.eventName = function(evtObj:Object){
// Az eseménykezelő kód…
};
Megjegyzés: Flash MX-ben alkalmazható a callback mechanizmus a fentebb írtak alapján!
componentInstance.addEventListener("eventName", listenerObject);
- Több figyelőt is regisztrálhatunk ugyanahhoz a komponens példányhoz:
myButton.addEventListener("click", listener1);
myButton.addEventListener("click", listener2);
- Egy figyelőt is regisztrálhatunk több komponens példányhoz:
myButton.addEventListener("click", listener1);
myButton2.addEventListener("click", listener1);
A következő példa illusztrálja a fent leírtakat (a nyomógomb lenyomásakor kiírja a saját címkéjének szövegét):
myListener = new Object();
myListener.click = function(evt){
trace(evt.target.label);
}
myButton.addEventListener("click", myListener);
Az események kezelése elvégezhető egy ActionScript osztályban is, ha a komponenseket (melyek eseményeit figyeljük) egy filmklipbe ágyazzuk bele. Ebben az
esetben a listenerObject, ami az események figyelését végzi, maga a MovieClipből származtatott osztály, tehát az eseménykezelés egy osztályban a
következő formát ölti:
class ClassName extends MovieClip{
public function onLoad():Void {
componentInstance.addEventListener("eventName", this);
}
public function eventName(evtObj:Object):Void {
// Az eseménykezelő kód…
}
}
A következő példa egy ActionScript osztályt ír le, ami egy szövegdoboz (TextInput) és három választógomb (RadioButton) komponens eseményeinek egy
lehetséges kezelését mutatja be.
import mx.controls.TextInput;
import mx.controls.RadioButton;
class Pelda extends MovieClip
{
// Komponens deklarációk
var TI:TextInput;
var RB1:RadioButton;
var RB2:RadioButton;
var RB3:RadioButton;
// Események és komponensek összekapcsolása
public function onLoad():Void
{
TI.addEventListener("change", this);
RB1.addEventListener("click", this);
RB2.addEventListener("click", this);
RB3.addEventListener("click", this);
}
// A "change" eseménykezelője
public function change(event:Object):Void
{
if (event.target == TI) {
// Kód helye
}
}
// A "click" eseménykezelője
public function click(event:Object):Void
{
switch (event.target) {
case RB1:
case RB2:
case RB3:
// Kód helye
break;
}
}
}
2.6. Idővonalak
_root - Fő idővonal meghívása
A Flash film legfelső szintje, azaz a gyökér vagy más néven a fő idővonal.
Gyakran használt parancs, de én mégsem javaslom a használatát túl gyakran. Ha ezt használod, ne ágyazd be a filmedet sehova. Azaz ha loadMovie-t
használsz erre a mozira, akkor a _root annak a gyökerére mutat, amibe beágyaztad a mozit. Nem biztos, hogy ez mindig jó.
Használata:
_root.flash_mc_var=0;
_parent - Egy szinttel feljebbi idővonal meghívása
Az adott MovieClipen (-ben) használat esetén az MC előtti idővonal. Azaz, ha egy MC-ben használod és az MC az a
_root-on van, akkor a
_parent azonos a
_root idővonallal. De ezzel mindig csak egy szintet lépsz vissza a hierarchiában.
Használata:
_parent._parent._parent.gotoAndPlay(1)
itt 3 szintet létünk vissza.
this - Saját idővonal meghívása
Amikor tanulgattam a Flash-t, először én is elgondolkodtam, hogy ez mire jó. Azonban rá kellett jönnöm: nagyon is fontos. Ezzel tudunk úgy beavatkozni az
adott időfolyamba, hogy az adott idővonal pontos nevét tudnánk. Ez főként az osztályoknál, függvényeknél és ciklusoknál fogjuk alkalmazni.
Használata:
onClipEvent(enterFrame){
this._alpha+=5
}
_leveln - Szint meghatározása
Ha egy MC-t a loadMovie("movi.swf",n) paranccsal töltünk be az n-edik mélységbe, akkor a legkönnyebben a _leveln parancsal tudunk hozzáférni, úgy hogy az
n helyére beírjuk a loadMovie-ban használt mélységet. A
_root = _level0.
Használata:
_level3.movie_mc.gotoAndStop(2);