Flash.jpw

  • Obecné
  • Adobe Flash
  • ActionScript 1 & 2.0
  • ActionScript 3.0
  • ActionScript 3.0

  • Úvod do ActionScriptu 3.0
  • Nové jazykové pomůcky
  • Metody a funkce
  • Třídy
  • Systém událostí
  • Display objekty a Display list
  • Regulární výrazy
  • XML a E4X
  • Zvuk
  • Internetová komunikace
  • Předchozí: Třídy
  • Následující: Display objekty a Display list
  • Systém událostí

    Event framework doznal oproti předchozí generaci poměrně rozsáhlých změn. Krkolomný model broadcaster-handler naradil modernější event-flow a jednotlivé typy událostí byly sjednoceny do nezávislých objektů.

    Asynchronní událost

    Událost, kterou spouští nezávislý vliv - například kliknutí, vypršení timeru nebo odpověď serveru. Po spuštění běží paralelně ke zbytku programu.

    Event Framework AS2 popisuje stručně stránka Úvod do ActionScriptu a podrobněji Asynchronní události.

    Tok události

    Fáze toku události od místa vzniku k cíli

    V AS2 byla událost zachycena vždy nejbližším objektem s definovaným event-handlerem. Definovat kliknutí pro celý MovieClip tak znamenalo zablokování přístupu k tlačítkům v něm obsaženým.

    AS3 zavádí event-flow

    Událost protéká od místa svého vzniku směrem k cílovému objektu a po jeho dosažení se vrací zpět.

    Obrázek vpravo ukazuje fáze toku při kliknutí na tlačítko uvnitř dvou úrovní MovieClipů.

    Při kliknutí na tlačítko je jako cíl určen objekt pod kurzorem myši s největší hloubkou, tedy objekt Button. Události myši vysílá samotné jádro Flashe, počáteční pozicí toku je tedy samotná scéna. V první fázi událost klesá dovnitř objektové hierarchie k cíli. Cestou ji může zaznamenat listener na libovolné úrovni. Po dosažení cíle se pak stejným způsobem vrací zpět k povrchu.

    Připojení listeneru k objektu

    V AS3 je jeden jediný způsob připojení listeneru k objektu. Pomocí metody addEventListener.

    objekt.addEventListener(MouseEvent.CLICK, clickListener);
     
    function clickListener(event:MouseEvent):void {
    	trace('klik');
    }

    Vidíte, že metoda addEventListener má definovány dva argumenty, celkem jich může mít definováno pět, jak ukazuje následující tabulka.

    type:StringTyp události. Přestože je možné použít běžný řetězec, například "click", používají se raději konstanty s touto hodnotou (MouseEvent.CLICK), jejich existenci totiž může kompliler zkontrolovat a hned upozornit na případný překlep. Také je hned vidět, jaký typ události bude listener očekávat.
    listener:FunctionMetoda, která slouží jako listener.
    useCapture:BooleanUrčuje, zda se má zachytit událost už v první, capturing, fázi toku události. Implicitně vypnuto.
    priority:intPriorita. Pokud má objekt více stejných listenerů, pomocí priority je možné určit jejich pořadí.
    useWeakReference:BooleanPoužít slabou vazbu objektu s listenerem. Implicitně vypnuto. Pokud volbu povolíte, nebude vytvořena vazba na listener a garbage-collector jej bude moci odstranit. Pokud byste takto použili lokální (vnitřní) funkci bez dalších vazeb, bude odstraněna ještě před vznikem události a tedy nebude fungovat.

    Objekt Event

    Argument listeneru je vždy objekt typu flash.events.Event, nebo jeho odvozenina. Uvnitř tohoto objektu se nachází některé důležité vlastnosti.

    Obecné vlastnosti objektu Event

    type:StringTyp události
    bubbles:BooleanOznačuje, jestli událost má třetí fázi toku (bubbling). Většina ji má, některé ovšem ne, například Event.ACTIVATE.
    eventPhase:uintAktuální fáze toku události. Nabývá hodnot 1, 2 a 3. Tyto hodnoty jsou také uloženy v konstantách objektu flash.events.EventPhase.
    target:ObjectCílový objekt události
    currentTarget:ObjectNadřazený objekt cíle, který je schopen zpracovat událost připojeným listenerem. U složitějších celků, jako jsou komponenty, je cílem události interní objekt, ale listenery připojuje až některý z jeho rodičů. Například při kliknutí na tlačítko bude target události nejhlubší objekt pod kurzorem - například popisek nebo ikonka tlačítka, což je vcelku nepotřebná reference. Pak je třeba referenci hledat ve vlastnosti currentTarget.
    cancelable:BooleanFlash má velké množství předdefinovaných akcí pro určité události. Vlastnost cancelable značí, že událost má u daného cíle definovány nějaké vnitřní akce, které mohou být potlačeny metodou preventDefault(). Ukážeme si dále.
    function clickListener(event:MouseEvent):void {
    	var target:Button = event.currentTarget as Button;
    	target.enabled = false;
    }

    Toto jsou základní vlastnosti. Odvozené objekty pak doplňují velké množství dalších - souvisejících s daným typem události. Například MouseEvent obsahuje vlastnosti pro zjištění pozice myši, informace o stisknutých klávesách a tak dále.

    Zastavení toku události

    Někdy je třeba ukončit tok události a zabránit tak v aktivaci dalších listenerů po jeho cestě. Lze to provést ve kterékoliv fázi metodou stopPropagation respektive stopImmediatePropagation.

    function clickListener(event:MouseEvent):void {
    	event.stopImmediatePropagation();	// okamžitě ukončí tok události
    }

    stopPropagation je jemnější varianta, která dovolí události aktivovat ještě listenery aktuálního objektu, než ukončí tok.

    Odpojení listeneru

    Odpojení listeneru probíhá obdobně jako jeho připojení.

    objekt.removeEventListener(MouseEvent.CLICK, clickListener);

    Aby byl listener nalezen a odstraněn, je třeba dodržet shodnost všech parametrů.

    Zrušení předdefinovaných akcí

    Některé objekty mají implicitně definovány akce pro určité události. Vlastnost cancelable pak značí, že tyto akce můžou být potlačeny.

    textfield.addEventListener(TextEvent.TEXT_INPUT, textfieldListener);
     
    function textfieldListener(event:TextEvent):void {
    	if(event.cancelable){
    		event.preventDefault();
    	}
    }

    Zde například potlačujeme předdefinovanou událost vkládání textu do textového pole. Při psaní tak textové pole nebude reagovat.

    Ověření existence listeneru

    Pro ověření existence listeneru se používají dvě metody: hasEventListener a willTrigger.

    objekt.hasEventListener(MouseEvent.CLICK);	// true

    Zatímco hasEventListener kontroluje existenci listeneru dané události připojeného přímo k danému objektu, willTrigger ověřuje, jestli nedojde k aktivaci listeneru i u některého z hlubších potomků objektu.

    Vlastní Event-dispatcher

    Také vlastní třídy mohou používat události pro své interní potřeby. Aby mohla třída vysílat a spravovat události, musí rozšiřovat třídu flash.events.EventDispatcher.

    Třída pak získá metody pro práci s událostmi, především pak dispatchEvent pro jejich vyslání a addEventListener pro připojení listeneru.

    package {
     
    	import flash.events.EventDispatcher;
    	import flash.events.Event;
     
    	public class storage extends EventDispatcher {
     
    		public static const STORAGE_FULL:String = 'storage_full';
    		private var data:Array = [];
     
    		public function addItem(item:*):void {
     
    			data.push(item);
     
    			if(this.data.length >= 5){
    				dispatchEvent(new Event(STORAGE_FULL));
    }	}	}	}

    Všimněte si, že pro název události definujeme veřejnou statickou konstantu STORAGE_FULL. Je to stejný doporučený postup použití názvu, jako u předdefinovaných událostí.

    var buffer:storage = new storage();
     
    buffer.addEventListener(storage.STORAGE_FULL, function(e:Event):void {
    	trace('buffer je plný');   
    });
     
    buffer.addItem('a');
    buffer.addItem('b');
    buffer.addItem('c');
    buffer.addItem(16);
    buffer.addItem('x');	// buffer je plný

    Rozhraní IEventDispatcher pro upravený Event-dispatcher

    Metody EventDispatcheru je někdy třeba upravit podle svých potřeb. Často se tak doplňují funkce pro lepší registraci událostí a jejich snazší hromadnou správu.

    V takovém případě se třída nerozšiřuje, ale ručně se implementuje rozhraní IEventDispatcher.

    package {
     
    import flash.events.IEventDispatcher;
    import flash.events.EventDispatcher;
    import flash.events.Event;
     
    class myDispatcher implements IEventDispatcher {       
     
        private var dispatcher:EventDispatcher;
     
        public function myDispatcher() {
            dispatcher = new EventDispatcher(this);
        }
     
     
        public function addEventListener(type:String,
                                         listener:Function,
                                         useCapture:Boolean = false,
                                         priority:int = 0,
                                         useWeakReference:Boolean = false):void{
            dispatcher.addEventListener(type, listener, useCapture, priority);
        }
        public function dispatchEvent(evt:Event):Boolean{
            return dispatcher.dispatchEvent(evt);
        }
        public function hasEventListener(type:String):Boolean{
            return dispatcher.hasEventListener(type);
        }
        public function removeEventListener(type:String,
                                            listener:Function,
                                            useCapture:Boolean = false):void{
            dispatcher.removeEventListener(type, listener, useCapture);
        }
        public function willTrigger(type:String):Boolean {
            return dispatcher.willTrigger(type);
        }
    }}

    Vidíte, že zde definujeme všech pět metod sami. Třídu EventDispatcher používáme už jen jako instanci, jejíž metody zajistí základní funkčnost našeho dispatcheru. Použití rozhraní není nezbytné, ale zajistí kontrolu správné implementace metod.