Většina programů, aby byla užitečná, musí reagovat na příkazy od uživatele. K tomu se programy Java spoléhají na události, které popisují akce uživatele.
Minulý měsíc jsem demonstroval, jak sestavit grafické uživatelské rozhraní z komponent poskytovaných sadou nástrojů pro abstraktní okna v knihovně tříd Java. Po sestavení několika takových rozhraní jsem krátce hovořil o tématu zpracování událostí, ale zastavil jsem se před úplným popisem zpracování událostí implementovaným AWT. Tento měsíc pokračujeme tam, kde jsme přestali.
Být poháněn událostmi
V dávné minulosti musel program, který chtěl vědět, co uživatel dělá, sám tyto informace aktivně shromažďovat. V praxi to znamenalo, že poté, co se program sám inicializoval, vstoupil do velké smyčky, ve které opakovaně zkoumal, zda uživatel nedělá něco zajímavého (například stiskne tlačítko, dotkne se klávesy, pohne posuvníkem, pohne myší) a poté podnikl příslušné kroky. Tato technika je známá jako hlasování.
Polling dokončí práci, ale má tendenci být nepraktický, když se používá v současných aplikacích, a to ze dvou souvisejících důvodů: Za prvé, použití dotazování má tendenci tlačit veškerý kód pro zpracování událostí do jednoho místa (uvnitř velké smyčky); zadruhé, výsledné interakce uvnitř velké smyčky bývají složité. Kromě toho dotazování vyžaduje, aby program seděl ve smyčce, spotřebovával cykly CPU a čekal, až uživatel něco udělá - vážné plýtvání cenným zdrojem.
AWT vyřešilo tyto problémy přijetím jiného paradigmatu, které je základem všech moderních okenních systémů: programování řízené událostmi. V rámci AWT patří všechny akce uživatele k abstraktní sadě tzv. Věcí Události. Událost dostatečně podrobně popisuje konkrétní akci uživatele. Spíše než program aktivně shromažďující události generované uživateli, doba běhu Java upozorní program, když dojde k zajímavé události. Programy, které zpracovávají interakci uživatelů tímto způsobem, jsou považovány za událost řízena.
Třída Událost
Třída Události je primárním hráčem ve hře událostí. Pokouší se zachytit základní charakteristiky všech událostí generovaných uživateli. stůl 1 uvádí seznam veřejných datových členů poskytovaných třídou Event.
Typ | název | Popis |
Objekt | cílová | Odkaz na komponentu, která událost původně přijala. |
dlouho | když | Časový okamžik, ve kterém k události došlo. |
int | id | Typ události (další informace najdete v části Typy událostí). |
int | X | Souřadnice x, ve které došlo k akci, relativně ke komponentě, která aktuálně zpracovává událost. U dané události se souřadnice x změní v hodnotě, jak se událost posune nahoru v hierarchii komponent. Počátek souřadné roviny je v levém horním rohu součásti. |
int | y | Souřadnice y, ve které došlo k akci, relativně ke komponentě, která událost aktuálně zpracovává. U dané události se souřadnice y změní v hodnotě, jak se událost posune nahoru v hierarchii komponent. Počátek souřadné roviny je v levém horním rohu součásti. |
int | klíč | U událostí na klávesnici klíčový kód právě stisknuté klávesy. Jeho hodnota bude obvykle hodnota Unicode znaku, který klíč představuje. Mezi další možnosti patří hodnoty pro speciální klávesy HOME, END, F1, F2 atd. |
int | modifikátory | Aritmeticky nebo kombinovaná kombinace hodnot SHIFT_MASK, CTRL_MASK, META_MASK a ALT_MASK. Jeho hodnota představuje stav kláves Shift, Control, Meta a Alt. |
int | clickCount | Počet po sobě jdoucích kliknutí myší. Tento datový člen je významný pouze v MOUSE_DOWN událostech. |
Objekt | arg | Argument závislý na události. Pro Button objekty je tento objekt String objekt, který obsahuje texturní štítek tlačítka. |
Jak vysvětlím v části s názvem Odeslání a šíření události, instance třídy Událost je obvykle vytvořena systémem run-time Java. Je však možné, aby program vytvářel a odesílal události komponentám prostřednictvím jejich postEvent ()
metoda.
Typy událostí
Jak již bylo uvedeno výše, třída Událost je modelem události uživatelského rozhraní. Události přirozeně spadají do kategorií na základě typu události (typ události je označen symbolem id
datový člen). Tabulka 2 uvádí všechny události definované AWT, seřazené podle kategorií.
Může být poučné vidět generování událostí v akci. Tlačítko na obrázku 1 po stisknutí vytvoří prohlížeč událostí, který zobrazí informace o událostech, které prohlížeč přijímá. Zdrojový kód prohlížeče událostí je k dispozici zde.
K prohlížení tohoto appletu potřebujete prohlížeč s podporou JavaObrázek 1: Generování událostí v akci
Odeslání a šíření události
Zvažte applet na obrázku 2. Skládá se ze dvou instancí třídy Button, vložených do instance třídy Panel. Tato instance třídy Panel je sama vložena do jiné instance třídy Panel. Druhá instance třídy Panel sedí pod instancí třídy TextArea a obě instance jsou vloženy do instance třídy Applet. Obrázek 3 představuje prvky, které tvoří tento applet rozložený jako strom, s instancemi TextArea a Button jako listy a instancí appletu jako kořen. (Další informace o hierarchickém uspořádání komponent v uživatelském rozhraní najdete v úvodu AWT z minulého měsíce.)
K prohlížení tohoto appletu potřebujete prohlížeč s podporou JavaObrázek 2: Třídy vložené do tříd
Obrázek 3: Strom prvků appletu (hierarchie)
Když uživatel interaguje s appletem na obrázku 2, vytvoří běhový systém Java instanci třídy Event a vyplní své datové členy informacemi popisujícími akci. Systém Java run-time pak umožňuje appletu zpracovat událost. Začíná to komponentou, která původně přijala událost (například tlačítkem, na které bylo kliknuto), a pohybuje se po stromě komponenty po komponentě nahoru, dokud nedosáhne kontejneru v horní části stromu. Každá součást má příležitost příležitost událost ignorovat nebo na ni reagovat jedním (nebo více) z následujících způsobů:
- Upravte datové členy instance události
- Proveďte akci a proveďte nějaký výpočet na základě informací obsažených v události
- Označte běhovému systému Java, že by se událost neměla šířit dále do stromu
Systém Java run-time předává informace o události komponentě prostřednictvím komponenty handleEvent ()
metoda. Všechny platné handleEvent ()
metody musí mít formu
public boolean handleEvent (Událost e)
Obslužná rutina události vyžaduje jednu informaci: odkaz na instanci třídy Event obsahující informace o události, ke které právě došlo.
Hodnota vrácená z handleEvent ()
metoda je důležitá. Označuje běhovému systému Java, zda událost byla nebo nebyla v rámci obslužné rutiny události zcela zpracována. Pravá hodnota označuje, že událost byla zpracována a šíření by se mělo zastavit. Falešná hodnota označuje, že událost byla ignorována, nemohla být zpracována nebo byla zpracována neúplně a měla by pokračovat ve stromu.
Zvažte následující popis interakce imaginárního uživatele s appletem na obrázku 2. Uživatel klikne na tlačítko označené „Jeden“. Systém běhu jazyka Java shromažďuje informace o události (počet kliknutí, umístění kliknutí, čas, kdy ke kliknutí došlo, a komponenta, která kliknutí přijala) a balí tyto informace v instanci třídy Event. Systém Java run-time pak začíná u komponenty, na kterou bylo kliknuto (v tomto případě tlačítko označené „One“) a prostřednictvím volání komponenty handleEvent ()
metoda, nabízí komponentě šanci reagovat na událost. Pokud komponenta událost nezpracovává nebo událost zpracovává neúplně (indikováno návratovou hodnotou false), běhový systém Java nabídne instanci Události další vyšší komponentě ve stromu - v tomto případě instanci Třída panelu. Běhový systém Java pokračuje tímto způsobem, dokud není událost zpracována nebo běhovému systému nedojdou komponenty k vyzkoušení. Obrázek 4 ukazuje cestu této události, jak se ji applet pokouší zpracovat.
Obrázek 4: Cesta události
Každá komponenta tvořící applet na obrázku 2 přidá do objektu TextArea řádek, který označuje, že obdržel událost. Potom umožňuje, aby se událost rozšířila na další komponentu ve stromu. Výpis 1 obsahuje kód typické handleEvent ()
metoda. Kompletní zdrojový kód pro tento applet je k dispozici zde.
public boolean handleEvent (Event evt) {if (evt.id == Event.ACTION_EVENT) {ta.appendText ("Panel" + str + "viděl akci ... \ n"); } else if (evt.id == Event.MOUSE_DOWN) {ta.appendText ("Panel" + str + "viděla myš dolů ... \ n"); }
návrat super.handleEvent (evt); }
Výpis 1: Typický handleEvent ()
metoda
Pomocné metody událostí
The handleEvent ()
metoda je jedno místo, kde může programátor vložit kód aplikace pro zpracování událostí. Občas se však komponenta bude zajímat pouze o události určitého typu (například události myši). V těchto případech může programátor umístit kód do a pomocná metoda, spíše než umístění do handleEvent ()
metoda.
Zde je seznam pomocných metod dostupných programátorům. Pro určité typy událostí neexistují žádné pomocné metody.
akce (Událost evt, Objekt co)
gotFocus (Event evt, Object what)
lostFocus (Event evt, Object what)
mouseEnter (Událost evt, int x, int y)
mouseExit (událost evt, int x, int y)
mouseMove (událost evt, int x, int y)
mouseUp (událost evt, int x, int y)
mouseDown (Událost evt, int x, int y)
mouseDrag (událost evt, int x, int y)
keyDown (událost evt, int klíč)
keyUp (událost evt, int klíč)
false k označení, že pomocná metoda událost nezpracovala.
Provádění handleEvent ()
metoda poskytovaná třídou Component vyvolá každou pomocnou metodu. Z tohoto důvodu je důležité, aby nově definované implementace handleEvent ()
metoda v odvozených třídách vždy končí příkazem
návrat super.handleEvent (e);
Kód v seznamu 2 ilustruje toto pravidlo.
public boolean handleEvent (Event e) {if (e.target instanceof MyButton) {// do something ... return true; }
návrat super.handleEvent (e); }
Výpis 2: Pravidlo pro ukončení příkazu v handleEvent ()
metoda
Nedodržení tohoto jednoduchého pravidla zabrání správnému vyvolání pomocných metod.
Obrázek 5 obsahuje applet, který zpracovává události myši pouze prostřednictvím kódu umístěného v pomocných metodách. Zdrojový kód je k dispozici zde.
událost | evt | Další událost v propojeném seznamu událostí. |
Události v okně | ||
Události okna jsou generovány v reakci na změny stavu okna, rámečku nebo dialogu. | ||
událost | ID | |
WINDOW_DESTROY | 201 | |
WINDOW_EXPOSE | 202 | |
WINDOW_ICONIFY | 203 | |
WINDOW_DEICONIFY | 204 | |
WINDOW_MOVED | 205 | |
Události na klávesnici | ||
Události klávesnice jsou generovány v reakci na stisknutí a uvolnění kláves, zatímco komponenta má vstupní fokus. | ||
událost | ID | |
KEY_PRESS | 401 | |
KEY_RELEASE | 402 | |
KEY_ACTION | 403 | |
KEY_ACTION_RELEASE | 404 | |
Myší události | ||
Události myši jsou generovány v reakci na akce myši, ke kterým dochází v rámci hranice komponenty. | ||
událost | ID | |
MOUSE_DOWN | 501 | |
MOUSE_UP | 502 | |
MOUSE_MOVE | 503 | |
MOUSE_ENTER | 504 | |
MOUSE_EXIT | 505 | |
MOUSE_DRAG | 506 | |
Posouvat události | ||
Události posouvání jsou generovány v reakci na manipulaci s posuvníky. | ||
událost | ID | |
SCROLL_LINE_UP | 601 | |
SCROLL_LINE_DOWN | 602 | |
SCROLL_PAGE_UP | 603 | |
SCROLL_PAGE_DOWN | 604 | |
SCROLL_ABSOLUTE | 605 | |
Seznam událostí | ||
Události seznamu jsou generovány v reakci na výběr provedený v seznamu. | ||
událost | ID | |
LIST_SELECT | 701 | |
LIST_DESELECT | 702 | |
Různé akce | ||
Různé události jsou generovány v reakci na různé akce. | ||
událost | ID | |
ACTION_EVENT | 1001 | |
LOAD_FILE | 1002 | |
ULOŽENÍ SOUBORU | 1003 | |
GOT_FOCUS | 1004 | |
LOST_FOCUS | 1005 |
Další informace o tomto tématu
- Výukový program Java Mary Campione a Kathy Walrath. Online verze konceptu je k dispozici na adrese //java.sun.com/tutorial/index.html.
Tento příběh, „Java a zpracování událostí“, původně publikoval JavaWorld.