Programmering

Java og hendelsesbehandling

De fleste programmer, for å være nyttige, må svare på kommandoer fra brukeren. For å gjøre dette stoler Java-programmer på hendelser som beskriver brukerhandlinger.

I forrige måned demonstrerte jeg hvordan jeg skulle sette sammen et grafisk brukergrensesnitt fra komponenter levert av Java-klassebibliotekets abstrakte vindusverktøy. Etter å ha samlet noen få slike grensesnitt, snakket jeg kort om temaet hendelsesbehandling, men jeg stoppet kort av en full beskrivelse av hendelsesbehandling som implementert av AWT. Denne måneden fortsetter vi der vi slapp.

Å være begivenhetsdrevet

I en fjern fortid måtte et program som ønsket å vite hva brukeren gjorde, aktivt samle inn slik informasjon selv. I praksis betydde dette at etter at et program var initialisert, gikk det inn i en stor sløyfe der det gjentatte ganger så ut for å se om brukeren gjorde noe interessant (for eksempel ved å trykke på en knapp, trykke på en tast, bevege en glidebryter, bevege musen) og deretter tok passende tiltak. Denne teknikken er kjent som avstemning.

Polling får jobben gjort, men har en tendens til å være uhåndterlig når den brukes i moderne applikasjoner av to relaterte grunner: For det første har bruken av polling en tendens til å skyve all hendelseshåndteringskode til ett sted (inne i den store sløyfen); for det andre har de resulterende interaksjonene i den store sløyfen en tendens til å være komplekse. I tillegg krever avstemning at et program skal sitte i en løkke og konsumere CPU-sykluser, mens de venter på at brukeren skal gjøre noe - et alvorlig sløsing med en verdifull ressurs.

AWT løste disse problemene ved å omfavne et annet paradigme, et som ligger til grunn for alle moderne vindussystemer: hendelsesdrevet programmering. Innenfor AWT tilhører alle brukerhandlinger et abstrakt sett med ting som kalles arrangementer. En hendelse beskriver, i tilstrekkelig detalj, en bestemt brukerhandling. I stedet for at programmet aktivt samler brukergenererte hendelser, varsler Java-kjøretiden programmet når en interessant hendelse inntreffer. Programmer som håndterer brukerinteraksjon på denne måten, sies å være det hendelsesdrevet.

Arrangementsklassen

Arrangementsklassen er den primære spilleren i arrangementsspillet. Den prøver å fange opp de grunnleggende egenskapene til alle brukergenererte hendelser. Tabell 1 lister opp de offentlige datamedlemmene levert av klassen Event.

TypeNavnBeskrivelse
GjenstandmålEn referanse til komponenten som opprinnelig mottok hendelsen.
langnårTidspunktet da hendelsen skjedde.
intidHendelsestypen (se seksjonen Hendelsestyper for mer informasjon).
intxX-koordinaten som handlingen skjedde i forhold til komponenten som for tiden behandler hendelsen. For en gitt hendelse vil x-koordinaten endres i verdi når hendelsen beveger seg oppover i komponenthierarkiet. Opprinnelsen til koordinatplanet er i komponentens øvre venstre hjørne.
intyY-koordinaten som handlingen skjedde i forhold til komponenten som for tiden behandler hendelsen. For en gitt hendelse vil y-koordinaten endres i verdi når hendelsen beveger seg oppover i komponenthierarkiet. Opprinnelsen til koordinatplanet er i komponentens øvre venstre hjørne.
intnøkkelFor tastaturhendelser ble tastekoden til tasten bare trykket. Verdien vil vanligvis være Unicode-verdien til tegnet nøkkelen representerer. Andre muligheter inkluderer verdier for spesialtastene HJEM, SLUT, F1, F2, og så videre.
intmodifikatorerEn aritmetisk eller ønsket kombinasjon av verdiene SHIFT_MASK, CTRL_MASK, META_MASK og ALT_MASK. Verdien representerer tilstanden til henholdsvis skift, kontroll, meta og alt.
intclickCountAntall museklikk på rad. Dette data-medlemmet er bare viktig i MOUSE_DOWN-hendelser.
GjenstandargEt hendelsesavhengig argument. For Button-objekter er dette objektet et strengobjekt som inneholder teksturetiketten til knappen.
Tabell 1: Offentlige data medlemmer levert av klasse Event

Som jeg vil forklare i delen med tittelen Arrangementssending og formidling, er en forekomst av klasse Hendelse vanligvis opprettet av Java run-time system. Det er imidlertid mulig for et program å lage og sende hendelser til komponenter via deres postEvent () metode.

Arrangementstyper

Som nevnt ovenfor er hendelsesklassen en modell av et brukergrensesnitt. Arrangementer faller naturlig inn i kategorier basert på typen hendelse (hendelsestypen indikeres av id data-medlem). Tabell 2 viser alle hendelsene definert av AWT, sortert etter kategori.

Tabell 2: Hendelser definert av AWT, sortert etter kategori

Det kan være lærerikt å se hendelsesgenerering i aksjon. Knappen i figur 1, når den trykkes, oppretter en hendelsesleser som viser hendelsesinformasjon om hendelsene nettleseren mottar. Kildekoden for hendelsesleseren er tilgjengelig her.

Du trenger en Java-aktivert nettleser for å se denne appleten

Figur 1: Hendelsesgenerering i aksjon

Arrangementssending og formidling

Tenk på appleten i figur 2. Den består av to forekomster av Button-klassen, innebygd i en forekomst av Panel-klassen. Denne forekomsten av Panel-klassen er selv innebygd i en annen forekomst av Panel-klassen. Den siste forekomsten av Panel-klassen ligger under en forekomst av klassen TextArea, og begge forekomster er innebygd i en forekomst av Applet-klassen. Figur 3 presenterer elementene som utgjør denne appleten som er lagt ut som et tre, med TextArea- og Button-forekomster som bladene, og en Applet-forekomst som roten. (For mer informasjon om den hierarkiske utformingen av komponenter i et brukergrensesnitt, les forrige måneds introduksjon til AWT.)

Du trenger en Java-aktivert nettleser for å se denne appleten

Figur 2: Klasser innebygd i klasser

Figur 3: Tre av appletelementer (hierarki)

Når en bruker samhandler med appleten i figur 2, oppretter Java-kjøretidssystemet en forekomst av klasse Event og fyller sine datamedlemmer med informasjon som beskriver handlingen. Java-kjøretidssystemet lar deretter appleten håndtere hendelsen. Det begynner med komponenten som opprinnelig mottok hendelsen (for eksempel knappen som ble klikket på) og beveger seg opp komponenttreet, komponent for komponent, til den når beholderen øverst på treet. Underveis har hver komponent muligheten til å ignorere hendelsen eller reagere på den på en (eller flere) av følgende måter:

  • Endre datamedlemmene til hendelsesforekomsten
  • Ta grep og utfør noen beregninger basert på informasjonen i arrangementet
  • Angi for Java-kjøretidssystemet at hendelsen ikke skal spre seg lenger opp i treet

Java kjøretidssystem overfører hendelsesinformasjon til en komponent via komponentens handleEvent () metode. Alle gyldige handleEvent () metoder må være av formen

public boolean handleEvent (Event e) 

En hendelsesbehandler krever en enkelt informasjon: en referanse til forekomsten av hendelsesklassen som inneholder informasjon om hendelsen som nettopp skjedde.

Verdien returnert fra handleEvent () metoden er viktig. Det indikerer for Java kjøretidssystem om hendelsen har blitt håndtert fullstendig i hendelsesbehandleren eller ikke. En sann verdi indikerer at hendelsen er håndtert og forplantningen skal stoppe. En falsk verdi indikerer at hendelsen er ignorert, ikke kunne håndteres eller har blitt håndtert ufullstendig og bør fortsette oppover treet.

Tenk på følgende beskrivelse av en imaginær brukers interaksjon med appleten i figur 2. Brukeren klikker på knappen merket "One". Kjøretidssystemet på Java samler informasjon om hendelsen (antall klikk, plasseringen av klikket, tidspunktet klikket skjedde og komponenten som mottok klikket) og pakker den informasjonen i en forekomst av hendelsesklassen. Java-kjøretidssystemet begynner deretter på komponenten som ble klikket på (i dette tilfellet knappen merket "One"), og via en samtale til komponentens handleEvent () metode, gir komponenten en sjanse til å reagere på hendelsen. Hvis komponenten ikke håndterer hendelsen eller håndterer hendelsen ufullstendig (angitt med en returverdi på false), tilbyr Java-kjøretidssystemet hendelsesforekomsten til neste høyere komponent i treet - i dette tilfellet en forekomst av Panelet klasse. Java kjøretidssystem fortsetter på denne måten til hendelsen håndteres eller kjøretidssystemet går tom for komponenter for å prøve. Figur 4 illustrerer banen til denne hendelsen når appleten prøver å håndtere den.

Figur 4: Stien til en hendelse

Hver komponent som utgjør appleten i figur 2, legger til en linje i TextArea-objektet som indikerer at den mottok en hendelse. Deretter lar hendelsen forplante seg til neste komponent i treet. Oppføring 1 inneholder koden for en typisk handleEvent () metode. Den komplette kildekoden for denne appleten er tilgjengelig her.

public boolean handleEvent (Event evt) {if (evt.id == Event.ACTION_EVENT) {ta.appendText ("Panel" + str + "saw action ... \ n"); } annet hvis (evt.id == Event.MOUSE_DOWN) {ta.appendText ("Panel" + str + "så musen ned ... \ n"); }

returner super.handleEvent (evt); }

Oppføring 1: En typisk handleEvent () metode

Begivenhetshjelpermetoder

De handleEvent () metoden er ett sted en programmerer kan sette applikasjonskode for håndtering av hendelser. Noen ganger vil en komponent imidlertid bare være interessert i hendelser av en bestemt type (for eksempel mushendelser). I slike tilfeller kan programmereren plassere koden i en hjelpermetode, i stedet for å plassere den i handleEvent () metode.

Her er en liste over hjelpemetodene som er tilgjengelige for programmerere. Det er ingen hjelpemetoder for visse typer arrangementer.

handling (Event evt, Object what)

gotFocus (Event evt, Object what)

lostFocus (Event evt, Object what)

mouseEnter (hendelse evt, int x, int y)

mouseExit (hendelse evt, int x, int y)

mouseMove (hendelse evt, int x, int y)

mouseUp (hendelse evt, int x, int y)

mouseDown (hendelse evt, int x, int y)

mouseDrag (hendelse evt, int x, int y)

keyDown (hendelse evt, int-tast)

keyUp (hendelse evt, int-tast)

false for å indikere at hjelpemetoden ikke taklet hendelsen.

Gjennomføringen av handleEvent () metode levert av klasse Komponent påkaller hver hjelpermetode. Av denne grunn er det viktig at de omdefinerte implementeringene av handleEvent () metoden i avledede klasser slutter alltid med utsagnet

returner super.handleEvent (e);

Koden i Listing 2 illustrerer denne regelen.

public boolean handleEvent (Event e) {if (e.target instanceof MyButton) {// gjør noe ... return true; }

returner super.handleEvent (e); }

Oppføring 2: Regel for avslutning av uttalelse i handleEvent () metode

Unnlatelse av å følge denne enkle regelen vil forhindre riktig påkallelse av hjelpemetoder.

Figur 5 inneholder en applet som håndterer musehendelser utelukkende gjennom kode plassert i hjelpermetoder. Kildekoden er tilgjengelig her.

BegivenhetevtNeste arrangement i en lenket liste over hendelser.
Vindushendelser
Vindushendelser genereres som svar på endringer i tilstanden til et vindu, ramme eller dialog.
BegivenhetID
WINDOW_DESTROY201
WINDOW_EXPOSE202
WINDOW_ICONIFY203
WINDOW_DEICONIFY204
WINDOW_MOVED205
Tastaturhendelser
Tastaturhendelser genereres som svar på tastene som trykkes og slippes mens en komponent har inngangsfokus.
BegivenhetID
TASTETRYKK401
KEY_RELEASE402
KEY_ACTION403
KEY_ACTION_RELEASE404
Mushendelser
Mushendelser genereres som svar på mushandlinger som skjer innenfor grensen til en komponent.
BegivenhetID
MOUSE_DOWN501
MOUSE_UP502
MOUSE_MOVE503
MOUSE_ENTER504
MOUSE_EXIT505
MUSE_DRAG506
Bla gjennom hendelser
Rullehendelser genereres som svar på manipulering av rullefelt.
BegivenhetID
SCROLL_LINE_UP601
SCROLL_LINE_DOWN602
SCROLL_PAGE_UP603
SCROLL_PAGE_DOWN604
SCROLL_ABSOLUTE605
Liste hendelser
Listehendelser genereres som svar på valg som er gjort i en liste.
BegivenhetID
LIST_SELECT701
LIST_DESELECT702
Diverse hendelser
Diverse hendelser genereres som svar på en rekke handlinger.
BegivenhetID
ACTION_EVENT1001
LOAD_FILE1002
LAGRE FILEN1003
GOT_FOCUS1004
LOST_FOCUS1005
Todd Sundsted har programmert siden datamaskiner ble tilgjengelige i stasjonære modeller. Selv om han opprinnelig var interessert i å bygge distribuerte objektapplikasjoner i C ++, flyttet Todd til Java-programmeringsspråket da Java ble et opplagt valg for den slags ting. I tillegg til å skrive, tilbyr Todd internett- og webapplikasjonskonsulenttjenester til selskaper i det sørøstlige USA.

Lær mer om dette emnet

  • Java-veiledningen av Mary Campione og Kathy Walrath. Den elektroniske utkastversjonen er tilgjengelig på //java.sun.com/tutorial/index.html.

Denne historien, "Java and event handling", ble opprinnelig utgitt av JavaWorld.

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