Programování

Java a zpracování událostí

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.

TypnázevPopis
ObjektcílováOdkaz na komponentu, která událost původně přijala.
dlouhokdyžČasový okamžik, ve kterém k události došlo.
intidTyp události (další informace najdete v části Typy událostí).
intXSouř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.
intySouř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.
intklíč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.
intmodifikátoryAritmeticky 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.
intclickCountPočet po sobě jdoucích kliknutí myší. Tento datový člen je významný pouze v MOUSE_DOWN událostech.
ObjektargArgument závislý na události. Pro Button objekty je tento objekt String objekt, který obsahuje texturní štítek tlačítka.
Tabulka 1: Veřejné datové členy poskytnuté třídou Událost

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í.

Tabulka 2: Události definované AWT, seřazené podle kategorie

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 Java

Obrá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 Java

Obrá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álostevtDalší 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álostID
WINDOW_DESTROY201
WINDOW_EXPOSE202
WINDOW_ICONIFY203
WINDOW_DEICONIFY204
WINDOW_MOVED205
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álostID
KEY_PRESS401
KEY_RELEASE402
KEY_ACTION403
KEY_ACTION_RELEASE404
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álostID
MOUSE_DOWN501
MOUSE_UP502
MOUSE_MOVE503
MOUSE_ENTER504
MOUSE_EXIT505
MOUSE_DRAG506
Posouvat události
Události posouvání jsou generovány v reakci na manipulaci s posuvníky.
událostID
SCROLL_LINE_UP601
SCROLL_LINE_DOWN602
SCROLL_PAGE_UP603
SCROLL_PAGE_DOWN604
SCROLL_ABSOLUTE605
Seznam událostí
Události seznamu jsou generovány v reakci na výběr provedený v seznamu.
událostID
LIST_SELECT701
LIST_DESELECT702
Různé akce
Různé události jsou generovány v reakci na různé akce.
událostID
ACTION_EVENT1001
LOAD_FILE1002
ULOŽENÍ SOUBORU1003
GOT_FOCUS1004
LOST_FOCUS1005
Todd Sundsted programuje od doby, kdy byly počítače k ​​dispozici pro stolní modely. Ačkoli se Todd původně zajímal o vytváření distribuovaných objektových aplikací v C ++, přešel na programovací jazyk Java, když se Java stala jasnou volbou pro tento druh věcí. Kromě psaní Todd poskytuje internetové a webové aplikační poradenské služby společnostem v jihovýchodních Spojených státech.

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.

$config[zx-auto] not found$config[zx-overlay] not found