Detektory zdarzeń, które nazywane są również modułami obsługi zdarzeń, to funkcje wykonywane przez programy Flash Player i AIR w odpowiedzi na określone zdarzenia. Dodawanie detektora zdarzeń jest procesem dwuetapowym. Najpierw należy utworzyć funkcję lub metodę klasy (dla programu Flash Player albo AIR), która zostanie wywołana w odpowiedzi na zdarzenie. Ta funkcja jest czasami nazywana funkcją detektora lub funkcją modułu obsługi zdarzeń. Następnie należy użyć metody
addEventListener()
w celu zarejestrowania funkcji detektora w celu zdarzenia lub w dowolnym obiekcie listy wyświetlania, który znajduje się w odpowiednim strumieniu zdarzenia.
Tworzenie funkcji detektora
Tworzenie funkcji detektora to jedyny aspekt, który odróżnia model zdarzeń języka ActionScript 3.0 od modelu zdarzeń DOM. Model zdarzeń DOM wyraźnie odróżnia detektor zdarzeń od funkcji detektora: detektor jest instancją klasy, która implementuje interfejs EventListener, a funkcja detektora jest metodą tej klasy, o nazwie
handleEvent()
. W modelu zdarzeń DOM należy zarejestrować instancję klasy, która będzie zawierała funkcję detektora zamiast rzeczywistego detektora.
W języku ActionScript 3.0 detektor zdarzenia nie jest odróżniany od funkcji detektora. Język ActionScript 3.0 nie udostępnia interfejsu EventListener, a funkcje detektora mogą być definiowane poza klasą lub jako część klasy. Ponadto funkcje detektora nie muszą mieć nazwy
handleEvent()
— nazwą może być dowolny poprawny identyfikator. W języku ActionScript 3.0 rejestrowana jest nazwa rzeczywistej funkcji detektora.
Funkcja detektora zdefiniowana poza klasą
Poniższy kod tworzy prosty plik SWF, który powoduje wyświetlenie czerwonego kwadratu. Funkcja detektora o nazwie
clickHandler()
, która nie jest częścią klasy, wykrywa kliknięcia czerwonego kwadratu.
package
{
import flash.display.Sprite;
public class ClickExample extends Sprite
{
public function ClickExample()
{
var child:ChildSprite = new ChildSprite();
addChild(child);
}
}
}
import flash.display.Sprite;
import flash.events.MouseEvent;
class ChildSprite extends Sprite
{
public function ChildSprite()
{
graphics.beginFill(0xFF0000);
graphics.drawRect(0,0,100,100);
graphics.endFill();
addEventListener(MouseEvent.CLICK, clickHandler);
}
}
function clickHandler(event:MouseEvent):void
{
trace("clickHandler detected an event of type: " + event.type);
trace("the this keyword refers to: " + this);
}
Gdy użytkownik oddziałuje na wynikowy plik SWF, klikając kwadrat, program Flash Player lub AIR generuje następujący wynik śledzenia:
clickHandler detected an event of type: click
the this keyword refers to: [object global]
Należy zauważyć, że obiekt zdarzenia został wprowadzony jako argument do
clickHandler()
. Dzięki temu funkcja detektora może sprawdzić obiekt zdarzenia. W tym przykładzie właściwość
type
obiektu zdarzenia służy do sprawdzenia, czy zdarzenie jest kliknięciem.
W przykładzie sprawdzana jest także wartość słowa kluczowego
this
. W tym przypadku
this
reprezentuje globalny obiekt, co ma sens, ponieważ funkcja jest zdefiniowana poza wszystkimi niestandardowymi klasami i obiektami.
Funkcja detektora zdefiniowana jako metoda klasy
Poniższy przykład jest taki sam, jak poprzedni, który definiował klasę ClickExample, ale różni się tym, że funkcja
clickHandler()
jest zdefiniowana jako metoda klasy ChildSprite:
package
{
import flash.display.Sprite;
public class ClickExample extends Sprite
{
public function ClickExample()
{
var child:ChildSprite = new ChildSprite();
addChild(child);
}
}
}
import flash.display.Sprite;
import flash.events.MouseEvent;
class ChildSprite extends Sprite
{
public function ChildSprite()
{
graphics.beginFill(0xFF0000);
graphics.drawRect(0,0,100,100);
graphics.endFill();
addEventListener(MouseEvent.CLICK, clickHandler);
}
private function clickHandler(event:MouseEvent):void
{
trace("clickHandler detected an event of type: " + event.type);
trace("the this keyword refers to: " + this);
}
}
Gdy użytkownik oddziałuje na wynikowy plik SWF, klikając czerwony kwadrat, program Flash Player lub AIR generuje następujący wynik śledzenia:
clickHandler detected an event of type: click
the this keyword refers to: [object ChildSprite]
Należy zauważyć, że słowo kluczowe
this
odwołuje się do instancji ChildSprite o nazwie
child
. Jest to zmiana w porównaniu z wersją ActionScript 2.0. Użytkownicy, którzy korzystali ze składników w wersji ActionScript 2.0, mogą pamiętać, że wprowadzenie metody klasy do
UIEventDispatcher.addEventListener()
powodowało ograniczenie zakresu metody do składnika, który rozgłaszał zdarzenie, a nie do klasy, w której zdefiniowano metodę detektora. Innymi słowy: jeśli ta technika była używana w wersji ActionScript 2.0, słowo kluczowe
this
odwoływało się do składnika rozgłaszającego zdarzenie, a nie do instancji ChildSprite.
Dla niektórych programistów takie rozwiązanie stanowiło problem, ponieważ oznaczało to, że nie mogli uzyskać dostępu do innych metod i właściwości klasy zawierającej metodę detektora. W celu obejścia tego problemu programiści korzystający z ActionScript 2.0 mogli użyć klasy
mx.util.Delegate
w celu zmiany zakresu metody detektora. Nie jest to już konieczne, ponieważ język ActionScript 3.0 tworzy metodę ograniczenia po wywołaniu metody
addEventListener()
. W rezultacie słowo kluczowe
this
odwołuje się do instancji ChildSprite o nazwie
child
, a programista ma dostęp do innych metod i właściwości klasy ChildSprite.
Detektor zdarzeń, który nie powinien być używany
Istnieje również trzecia technika, która służy do tworzenia obiektu ogólnego zawierającego właściwość, która wskazuje na dynamicznie przypisywaną funkcję detektora, ale jej używanie nie jest zalecane. Ta technika została omówiona w niniejszej sekcji, ponieważ była często stosowana w języku ActionScript 2.0 — w języku ActionScript 3.0 nie powinna być używana. Ta technika nie jest zalecana, ponieważ słowo kluczowe
this
będzie odwoływało się do obiektu globalnego zamiast do obiektu detektora.
Poniższy przykład jest taki sam, jak poprzedni przykład klasy ClickExample, ale różni się tym, że funkcja detektora jest zdefiniowana jako część obiektu ogólnego o nazwie
myListenerObj
:
package
{
import flash.display.Sprite;
public class ClickExample extends Sprite
{
public function ClickExample()
{
var child:ChildSprite = new ChildSprite();
addChild(child);
}
}
}
import flash.display.Sprite;
import flash.events.MouseEvent;
class ChildSprite extends Sprite
{
public function ChildSprite()
{
graphics.beginFill(0xFF0000);
graphics.drawRect(0,0,100,100);
graphics.endFill();
addEventListener(MouseEvent.CLICK, myListenerObj.clickHandler);
}
}
var myListenerObj:Object = new Object();
myListenerObj.clickHandler = function (event:MouseEvent):void
{
trace("clickHandler detected an event of type: " + event.type);
trace("the this keyword refers to: " + this);
}
Wyniki będą następujące:
clickHandler detected an event of type: click
the this keyword refers to: [object global]
Można by oczekiwać, że słowo kluczowe
this
będzie odwoływało się do
myListenerObj
oraz że wynikiem będzie
[object Object]
, ale słowo kluczowe odwołuje się do obiektu globalnego. Gdy nazwa właściwości dynamicznej zostanie wprowadzona jako argument metody
addEventListener()
, program Flash Player lub AIR nie może utworzyć metody ograniczenia. Dzieje się tak dlatego, że element wprowadzany jako parametr
listener
jest tylko adresem funkcji detektora w pamięci, a program Flash Player i AIR nie może powiązać tego adresu z instancją
myListenerObj
.
Zarządzanie detektorami zdarzeń
Do zarządzania funkcjami detektora służą metody interfejsu IEventDispatcher. Interfejs IEventDispatcher jest wersją interfejsu EventTarget modelu zdarzeń DOM, jaka jest dostępna w języku ActionScript 3.0. Nazwa IEventDispatcher może wskazywać na to, że głównym celem jest wysyłanie (lub wywoływanie) obiektów zdarzeń, jednak metody tej klasy są używane znacznie częściej w celu rejestrowania detektorów zdarzeń, sprawdzania dostępności detektorów zdarzeń oraz usuwania detektorów zdarzeń. Interfejs IEventDispatcher definiuje pięć metod, co przedstawia poniższy kod:
package flash.events
{
public interface IEventDispatcher
{
function addEventListener(eventName:String,
listener:Object,
useCapture:Boolean=false,
priority:Integer=0,
useWeakReference:Boolean=false):Boolean;
function removeEventListener(eventName:String,
listener:Object,
useCapture:Boolean=false):Boolean;
function dispatchEvent(eventObject:Event):Boolean;
function hasEventListener(eventName:String):Boolean;
function willTrigger(eventName:String):Boolean;
}
}
API programu Flash Player API implementuje interfejs IEventDispatcher z klasą EventDispatcher, która służy jako klasa podstawowa dla wszystkich klas, które mogą być celami zdarzeń lub mogą stanowić część strumienia zdarzenia. Przykład: klasa DisplayObject dziedziczy od klasy EventDispatcher. Oznacza to, że każdy obiekt na liście wyświetlania ma dostęp do metod interfejsu IEventDispatcher.
Dodawanie detektorów zdarzeń
Metoda
addEventListener()
jest najważniejszą metodą roboczą interfejsu IEventDispatcher. Służy do rejestrowania funkcji detektorów. Ma dwa wymagane parametry:
type
i
listener
. Parametr
type
służy do określania typu detektora. Parametr
listener
służy do wybierania funkcji detektora, która będzie wywoływana, gdy wystąpi zdarzenie. Parametr
listener
może odwoływać się do funkcji lub metody klasy.
Do określania parametru
listener
nie należy używać nawiasów. Na przykład: funkcja
clickHandler()
jest określona bez nawiasów w poniższym wywołaniu metody
addEventListener()
:
addEventListener(MouseEvent.CLICK, clickHandler)
Parametr
useCapture
metody
addEventListener()
umożliwia kontrolowanie fazy strumienia zdarzenia, w której detektor będzie aktywny. Jeśli dla metody
useCapture
zostanie ustawiona wartość
true
, detektor będzie aktywny w fazie przechwytywania strumienia zdarzenia. Jeśli dla metody
useCapture
zostanie ustawiona wartość
false
, detektor będzie aktywny podczas fazy docelowej i fazy propagacji strumienia zdarzenia. Aby wykrywać zdarzenie podczas wszystkich faz strumienia zdarzenia, należy dwukrotnie wywołać metodę
addEventListener()
— jeden raz, ustawiając dla metody
useCapture
wartość
true
, i drugi raz, ustawiając dla metody
useCapture
wartość
false
.
Parametr
priority
metody
addEventListener()
nie jest oficjalną częścią modelu zdarzenia DOM Level 3. Jest to część języka ActionScript 3.0 i zapewnia większą elastyczność w organizowaniu detektorów zdarzeń. Po wywołaniu metody
addEventListener()
można ustawić priorytet dla detektora zdarzenia — w tym celu jako parametr
priority
należy wprowadzić wartość całkowitą. Wartością domyślną jest 0, ale można ustawić ujemną lub dodatnią wartość całkowitą. Im wyższa jest wartość, tym szybciej detektor zdarzenia zostanie uruchomiony. Detektory zdarzeń o tym samym priorytecie są uruchamiane w kolejności, w jakiej są dodawane, więc im wcześniej detektor zostanie dodany, tym szybciej zostanie uruchomiony.
Parametr
useWeakReference
umożliwia określanie, czy odwołanie do funkcji detektora jest słabe czy normalne. Ustawienie dla parametru wartości
true
umożliwia uniknięcie sytuacji, w których funkcje detektora są przechowywane w pamięci, nawet gdy nie są już potrzebne. W programach Flash Player i AIR wykorzystywana jest technika o nazwie
czyszczenie pamięci
, która umożliwia usuwanie z pamięci obiektów nieużywanych. Obiekt jest traktowany jako nieużywany, jeśli nie istnieją żadne odwołania do tego obiektu. Moduł czyszczenia pamięci pomija słabe odwołania, co oznacza, że funkcja detektora, do której istnieje wyłącznie słabe odwołanie, jest odpowiednia do wyczyszczenia.
Usuwanie detektorów zdarzeń
Do usuwania zbędnych detektorów zdarzeń służy metoda
removeEventListener()
. Usuwanie detektorów, które nie będą używane, jest bardzo dobrym sposobem postępowania. Do wymaganych parametrów należą
eventName
i
listener
i są to te same parametry, jak parametry wymagane dla metody
addEventListener()
. Czytelnik z pewnością pamięta, że wykrywanie zdarzeń jest możliwe podczas wszystkich faz zdarzeń — w tym celu należy wywołać metodę
addEventListener()
dwukrotnie: raz, ustawiając dla
useCapture
wartość
true
, a następnie ponownie, ustawiając wartość
false
. W celu usunięcia obydwu detektorów zdarzeń należy wywołać metodę
removeEventListener()
dwukrotnie: raz, ustawiając dla
useCapture
wartość
true
, a następnie ponownie, ustawiając wartość
false
.
Wywoływanie zdarzeń
Metoda
dispatchEvent()
może być używana przez zaawansowanych programistów w celu wysyłania niestandardowych obiektów zdarzeń do strumienia zdarzeń. Jedynym parametrem akceptowanym przez tę metodę jest odwołanie do obiektu zdarzenia, które może być instancją klasy Event lub podklasą klasy Event. Po wywołaniu właściwość
target
obiektu zdarzenia jest ustawiana dla obiektu, dla którego wywołano metodę
dispatchEvent()
.
Sprawdzanie dostępności detektorów zdarzeń
Ostatnie dwie metody interfejsu IEventDispatcher udostępniają użyteczne informacje o istnieniu detektorów zdarzeń. Metoda
hasEventListener()
zwraca wartość
true
, jeśli istnieje detektor zdarzeń dla danego typu zdarzeń w konkretnym obiekcie listy wyświetlania. Metoda
willTrigger()
zwraca również wartość
true
, gdy detektor zdarzeń zostanie znaleziony dla konkretnego obiektu listy wyświetlania, ale metoda
willTrigger()
sprawdza dostępność detektorów nie tylko w obiekcie wyświetlanym, ale również we wszystkich przodkach obiektu listy wyświetlania, we wszystkich fazach strumienia zdarzenia.
Zdarzenia błędów bez detektorów
Głównym mechanizmem obsługi błędów w języku ActionScript 3.0 są wyjątki, a nie zdarzenia, ale obsługa wyjątków nie działa dla operacji asynchronicznych, takich jak ładowanie plików. Jeśli wystąpi błąd, taki jak operacja asynchroniczna, program Flash Player i AIR generuje obiekt zdarzenia błędu. Jeśli nie zostanie utworzony detektor dla zdarzenia błędu, w wersjach programów Flash Player i AIR, które obsługują debugowanie, zostaną wyświetlone okna dialogowe z informacjami o błędzie. Na przykład: w wersji programu Flash Player obsługującej debugowanie wyświetlane jest następujące okno dialogowe z opisem błędu, gdy w aplikacji wykonywana jest próba załadowania pliku z nieprawidłowego adresu URL:
Większość zdarzeń błędów jest oparta na klasie ErrorEvent i dlatego ma właściwość o nazwie
text
, która służy do zapisu komunikatu o błędzie, jaki jest wyświetlany w programie Flash Player lub AIR. Dwoma wyjątkami są klasy StatusEvent i NetStatusEvent. Obydwie te klasy mają właściwość
level
(
StatusEvent.level
i
NetStatusEvent.info.level
). Gdy wartość właściwości
level
jest równa "
error
", te typy zdarzeń są traktowane jako zdarzenia błędów.
Zdarzenie błędu nie spowoduje zatrzymania działania pliku SWF. Użytkownik zostanie powiadomiony o błędzie tylko przez okno dialogowe w wersjach wtyczek przeglądarki, które obsługują debugowanie, jako komunikat w panelu Wyjście w odtwarzaczu do tworzenia oraz jako wpis w pliku dziennika Adobe Flash Builder. W wydanych wersjach programu Flash Player i AIR błąd nie będzie się objawiał.
|
|
|