©Internetix


Javan tapahtumankäsittely


Ehkä suurimmat muutokset JDK 1.0:n ja JDK 1.1:n välillä liittyvät juuri tapahtumankäsittelyyn. Näiden versioiden tapahtumankäsittely eroaa toisistaan melkoisesti.

JDK 1.1:ssä ei tapahtumia edusta enää yksistään java.awt.Event-luokka, vaan käytössä on useiden tapahtumaluokkien hierarkia. Jokaisella tapahtumatyypillä on ns. pääluokka ja sen alla on tietyntyyppisten tapahtumien joukko.

Esimerkiksi pääluokka voi olla hiiritapahtuma tai vaikkapa näppäintapahtuma. Hiiritapahtuma -pääluokan alla ovat sitten kaikki mahdolliset hiiritapahtumat ja vastaavasti näppäintapahtuma -pääluokan alla kaikki näppäintapahtumat.

Seuraavassa tapahtumien pääluokat:

ActionEvent Kun käyttäjä valitsee jonkin graafisen elementin
AdjustmentEvent Kun käyttäjä siirtää esim. hissiä vierityspalkissa
ComponentEvent Kun käyttäjä muuttaa esim. komponentin kokoa tai sijaintia
ContainerEvent Kun containeriin lisätään tai poistetaan komponentteja
FocusEvent Kun komponentti saa/menettää fokuksen
InputEvent Päätapahtuma kaikille komponenteista aiheutuneille tapahtumille, eli tämä generoidaan ennen varsinaista tapahtumaa
ItemEvent Kun käyttäjä valitsee arvon esim. listasta
KeyEvent Kun käyttäjä painaa jotain näppäintä
MouseEvent Kun käyttäjä tekee jotain hiiren kanssa
TextEvent Kun käyttäjä editoi tekstikomponentin sisältöä
WindowEvent Kun käyttäjä muuttaa ikkunan ominaisuuksia

Näppäimistötapahtumat:

Näppäimistön luku toteutetaan tapahtumaluokalla KeyEvent. Tapahtumaluokkaan kuuluu joukko valmiita funktioita (metodeja), joiden avulla voidaan lukea tapahtuman aiheuttaneen näppäimen tiedot. Funktiot ovat:

getKeyChar() Painettua näppäintä vastaava merkki
getKeyCode() Painetun näppäimen koodi
getKeyModifiersText(int) Palauttaa erikoisnäppäimet
getKeyText(int) Palauttaa merkkijonon, jossa on näppäimen nimi (esim. F5)
isActionKey() Tosi, jos näppäin kytketty johonkin toimintoon

Lisäksi seuraavilla funktioilla voidaan muokata painetun näppäimen ominaisuuksia:

setKeyChar(char) Asettaa painetun näppäimen merkin
setKeyCode(int) Asettaa painetun näppäimen koodin
setModifiers(int) Asettaa erikoisnäppäimet

Seuraavassa on lueteltu vielä näppäintapahtumiin liittyvät takaisinkutsuttavat funktiot:

public void keyPressed (KeyEvent e) Kutsutaan, kun käyttäjä painaa jotain näppäintä
public void keyReleased (KeyEvent e) Kutsutaan, kun käyttäjä vapauttaa jonkin näppäimen
public void keyTyped (KeyEvent e) Kutsutaan, kun käyttäjä painaa jotain näppäintä ja vapauttaa sen välittömästi

Parametrina välitettävä KeyEvent-olio sisältää näppäintapahtuman kaikki tarvittavat tiedot näppäintapahtuman aiheuttaneesta näppäimestä. Seuraavassa on lueteltuna muutamia näppäinkoodeja, jotka voidaan tutkia vertaamalla niitä tapahtuman jälkeen getKeyCode()-funktiolla saatavaan arvoon:

VK_UP ylänuoli
VK_DOWN alanuoli
VK_RIGHT oikea nuoli
VK_LEFT vasen nuoli
VK_HOME <Home>-näppäin
VK_INSERT <Ins>-näppäin
VK_DELETE <Del>-näppäin
VK_PGDN <PageDown>
VK_PGUP <PageUp>
VK_F1-VK_F12 funktionäppäimet
VK_A-VK_Z Isot kirjaimet
VK_END <End>-näppäin jne ...

Nämä näppäinkoodien määrittelyt löytyvät Javan API-luokasta java.awt.event.KeyEvent.

Erikoisnäppäinten (esim. Shift, Alt ja Ctrl) luku tapahtuu myös getKeyCode()-funktiolla. Tämän funktion tulos ohjataan edelleenkin getKeyText()-funktiolle, jolloin saadaan tekstimuodossa painetun näppäimen nimi. (esim. SHIFT, ALT tai CTRL).

Seuraava esimerkki havainnollistaa näppäimistötapahtumien käsittelyä JDK 1.1:ssä:

Esim19


keyPressed-funktio olisi voitu myöskin toteuttaa seuraavasti:

Seuraavassa pieni selvitys edelliseen esimerkkiin liittyvistä tekniikoista:

Tapahtumien sallinta ja kuuntelijat:

Toisin kuin JDK 1.0:ssa, täytyy JDK 1.1:ssä olioiden sallia tapahtumat ennen kuin ne lähetetään ko. oliolle käsiteltäväksi.

Tapahtumat voidaan sallia olioiden setListener- ja addListener-funktioilla (metodeilla).

setListener-funktiolla sallitaan yksittäisjaettu tapahtuma, mikä tarkoittaa sitä, että vain yksi olio voi kuunnella tapahtumaa.

addListener-funktiolla puolestaan sallitaan ns. monijaettu tapahtuma, mikä tarkoittaa sitä, että useampi olio voi kuunnella tapahtumaa.

Kaikki AWT-komponentit tukevat ainoastaan monijaettuja tapahtumia, joten jatkossa käytämme lähes yksinomaan addListener-funktiota tapahtumien sallimiseen.

Jotta JDK 1.1:ssä voisi jokin olioluokka vastaanottaa viestejä, täytyy siitä tehdä ns. kuuntelija. Kuuntelija olio toteutetaan Listener-tajapinnan avulla. Jokaiselle päätapahtumalle on olemassa oma Listener-rajapinta. Listener-rajapintajako noudattaa yleistä tapahtumaluokkajakoa JDK 1.1:ssä) (vrt. aiemmat yleiset tapahtumaluokat).

Seuraavassa on lueteltu Listener-rajapintojen nimet:

ActionListener KeyListener
AdjustmentListener MouseListener
ComponentListener MouseMoveListener
FocusListener TextListener
ItemListener WindowListener

Edellisessä esimerkissä toteutimme Appletille ActionListener- ja KeyListener-rajapinnat, koska olimme kiinnostuneita näiden tapahtumaluokkien tapahtumista (ActionListener => Painonapin painalluksen käsittely ja KeyListener => Näppäinten käsittely).

Lisäksi sallimme ensimmäiselle painonapille (nappi1) näppäintapahtumat ja toiselle painonapille normaalit aktivointi-viestit (Click).

HUOMAA !!!, että kuuntelijarajapinnan (tässä esimerkissä Appletti) on toteutettava kaikki kuuntelemansa Listener-rajapinnan tapahtumafunktiot.

Esimerkiksi KeyListener-rajapinnalla on seuraavat tapahtumafunktiot:

keyPressed, keyReleased ja keyTyped

Eli kaikki nämä on toteutettava, vaikkei niitä käyttäisikään kuten meidänkin esimerkissämme.

ActionListener-rajapinnalla on ainoastaan yksi tapahtumafunktio:

actionPerformed

ActionListener-rajapintaa käytetään nimenomaan eri komponentteihin kohdistuneiden tapahtumien käsittelyyn (esim. tämän esimerkin painonapin tapahtumakäsittelijä).

Hiiritapahtumat:

Hiiritapahtumien käsittelyyn on JDK 1.1:ssä tarkoitettu tapahtumaluokat MouseEvent ja .

Seuraavassa on lueteltu em. olioiden funktiot (metodit), joiden avulla voidaan tutkia hiiritapahtumaan liittyvää tietoa:

getClickCount() Palauttaa klikkausten määrän
getPoint() Palauttaa hiiren koordinaatit Point-oliossa
getX() Hiiren X-koordinaatti
getY() Hiiren Y-koordinaatti
isPopupTrigger Tosi, jos Popup-menun valinta

JDK 1.1:ssä hiiritapahtumien käsittely toteutetaan kahdella kuuntelijalla:

MouseListener Vastaa hiiren nappien painalluksista/ vapautuksista
MouseMotionListener Vastaa hiiren raahaamisesta ja liikuttamisesta

Seuraavassa on kaikki MouseListener rajapinnan sisältämät funktiot ja niiden tarkoitus (muistathan, että kaikki nämä täytyy määritellä).

public void mousePressed (MouseEvent e) { } Reagoi hiiren vasemman näppäimen painallukseen
public void mouseClicked (MouseEvent e) { } Reagoi Komponenttien klikkauksiin (esim. painonapin painamiseen)
public void mouseReleased(MouseEvent e) { } Reagoi hiiren vasemman näppäimen vapautukseen
public void mouseEntered (MouseEvent e) { } Reagoi siihen että hiirikursori siirretään jonkin komponentin päälle
public void mouseExited (MouseEvent e) { } Reagoi siihen, että hiirikursori poistuu jonkin komponentin päältä
public void mouseDragged (MouseEvent e) { } Reagoi siihen, että hiirtä liikutetaan vasen näppäin pohjassa
public void mouseMoved (MouseEvent e) { } Kun hiirtä liikutetaan ilman vasemman napin painamista

Seuraavat esimerkit havainnollistavat hiiritapahtumien käsittelyä JDK 1.1:ssä.

Kun hiirtä liikutetaan, tulostetaan selaimen tilapalkkiin aina kulloisetkin hiiren koordinaatit:

Esim20

Tässä esimerkissä toteutamme jo aiemmin esillä olleen piirrustusohjelman JDK 1.1:n mukaisella tavalla:

Esim21

Tässä kappaleessa käsittelimme tapahtumankäsittelyä JDK 1.0:ssa ja JDK 1.1:ssä pääasiassa vain näppäimistö- ja hiiritaphtumien osalta.

Ainakin yhtä tärkeä tapahtumankäsittelyn osa-alue on erilaisiin käyttöliittymän komponentteihin kohdistuneet tapahtumat (esim. painonapin painaminen). Nämä tapahtumathan yleensä muodostavat nykyaikaisissa tapahtumaohjatuissa ohjelmissa pääosan niistä tapahtumista, joihin ohjelmassa reagoidaan (=kirjoitetaan käsittelijät)

Käyttöliittymäkomponentteihin kohdistuvien tapahtumien käsittelyyn tutustumme myöhemmin tässä opintojaksossa samassa yhteydessä grraafisten käyttöliittymäkomponenttien ohjelmoinnin kanssa.


Harjoituksia:

1. Toteuta piirto-ohjelmaan (Esim21) käyttäjälle mahdollisuus valita piirtoväri muutamasta vaihtoehdosta. Toteuta myös mahdollisuus muuttaa vaikkapa rullausjanan avulla pensselin paksuutta.
2. Joissain kännykkämalleissa on ns. "matopeli". Ota tämän kappaleen ensimmäinen esimerkki (Esim19) lähtökohdaksi ja ohjelmoi siitä yksinkertainen "matopeli" tai jokin muu vastaava nuolinäppäimillä ohjattava peli. Kokeile myös muiden näppäinten (kuin nuolinäppäimet) ohjelmointia.

ŠInternetix/Java-ohjelmointi/Jukka Selin 1999