Hello Web! II: järg

Muudame esimeses rakendis tehtud rakendi interaktiivsemaks. Moodustame klassile Applet uue alamklassi HelloWeb2:

import java.applet.Applet;
import java.awt.*;

public class HelloWeb2 extends Applet {
  int messageX = 125, messageY = 95;
  String theMessage;

  public void init() {
    theMessage = getParameter( "message" );
  }

  public void paint( Graphics gc ) {
    gc.drawString( theMessage, messageX, messageY );
  }

  public boolean mouseDrag( Event evt, int x, int y ) {
    messageX = x;
    messageY = y;
    repaint();
    return true;
  }
}
Kirjutage see tekst faili HelloWeb2.java ja kompileerige see. Tulemuseks on klassifail HelloWeb2.class. Seejärel kirjutage faili HelloWeb2.html järgmised read (võite ka juba olemasolevat faili HelloWeb.html täiendada):
<html>
<head></head>
<body>
<applet code=HelloWeb2 width=300 heigth=200>
<param name="message" value="Hello Web!">
</applet>
</body>
</html>
Siin see HelloWeb2.html on

Nautige nüüd teksti lohistamist mööda ekraani.

Import

Me lisasime programmi algusesse järgmised read:

import java.applet.Applet;
import java.awt.*;

public class HelloWeb2 extends Applet {.....}
Klass Applet pole meie poolt defineeritud ja seetõttu tuleb meil kompilaatorile öelda, kust seda otsida. Esimese käsu import abil ütlesimegi, et klass Applet kuulub paketti java.applet ning kompilaator teab nüüd, kust seda otsida.

Käsk import muudab programmeerimise mugavamaks - me võime programmis nüüd java.applet.Applet asemel kirjutada lihtsalt Applet. Teise import käsu tulemusel imporditakse kõik paketti java.awt kuuluvad klassid. Kuid klassi koodis kasutatakse ainult neid imporditud klasse, mida tegelikult kasutatakse. Java kompilaator ei lisa midagi ülearust. Meie näites kasutatakse ainult klassi java.awt.Graphics.

Näidise muutujad (instance variables)

Me lisasime näitesse mõned muutujad:

public class HelloWeb2 extends Applet {
  int messageX = 125, messageY = 95;
  String theMessage;
..........
messageX ja messageY on tüüpi integer ja hoiavad meie liigutatava objekti koordinaate. Neile on antud algväärtused. Java integer on 32-bitine märgiga number. Muutuja theMessage on tüüpi String ja saab hoida klassi String eksemplari.

Need kolm muutujat on defineeritud klassi sees, kuid mitte ühegi meetodi sees. Selliseid muutujaid nimetatakse eksemplari muutujateks, kuna nad kuuluvad kogu klassile, mitte mingile konkreetsele meetodile. Nende muutujate koopiad ilmuvad igasse antud klassi eksemplari. Eksemplari muutujaid saavad kõik antud klassi meetodid kasutada. Olenevalt nende muutujate piiritlejatest võib neid saada kasutada ka väljastpoolt klassi.

Kui muutujaid pole initsialiseeritud, siis numbri tüüpi muutujad saavad algväärtuseks 0, boolean tüüpi muutujad false ja objekti tüüpi muutujad null (see tähendab, et pole väärtust). Püüdes kasutada objekti väärtusega null, antakse runtime error.

Muutujaid, mis on defineeritud mingi kindla meetodi sees, nimetatakse lokaalseteks muutujateks (local variables). Neid muutujaid näeb ainult meetodi seest. Lokaalseid muutujaid Java ei initsialiseeri. Püüdes kasutada algväärtustamata lokaalset muutujat antakse compile-time error. Lokaalsed muutujad elavad ainult meetodi väljakutsumise ajal. Alati, kui meetod välja kutsutakse, luuakse lokaalsed muutujad uuesti ja neid tuleb algväärtustada.

Meetodid (methods)

Me muutsime pisut meetodit paint(). Nüüd on kõik selle meetodi argumendid muutujad.

Ka kaks uut meetodit on ilmunud klassi. Samamoodi nagu paint(), on ka need baasklassis Applet olemas, me lisasime üle defineerimisega omapoolse funktsionaalsuse. init() on tähtis meetod klassis Applet. Seda kutsutakse välja üks kord - siis kui rakend luuakse. init() on hea koht tegevustele, mida tuleb üks kord rakendi eluajal teha. init() kutsutakse Javat toetava Webi lehitseja poolt välja siis, kui valmistatakse ette rakendi ekraanile toomist.

public void init() {
    theMessage = getParameter( "message" );
  }
Meie üle defineeritud meetod init() annab muutujale theMessage väärtuse.

Kui HTML-lähtetekstis on <applet> sees antud parameetrid, siis neid hoitakse tabelis ja nad on kättesaadavad meetodi getParameter() abil. Antud parameetri nimele leiab see meetod String tüüpi väärtuse. Kui nime ei leita, tagastatakse väärtus null.

Meetodi getParameter() argumendile pole justkui tüüpi määratud - tüübi nimi muutuja eest puudub. Tegelikult on see muutuja aga tüüpi String - Java kompilaator muudab kõik jutumärkides stringid tüüpi String objektideks.

Me kasutasime meetodit getParameter() ilma objektinimelise eesliiteta. Seda võisime teha tänu sellele, et getParameter() on klassi Applet public meetod ja on klassi HelloWeb2 poolt sealt päritud. Kui meetod kuulub oma klassi või ta on päritud ülemklassist, siis võime teda kasutada ilma eesliiteta.

Read-only muutuja this abil saame viidata objektile endale. Meetod võib kasutada muutujat this viitamaks objekti eksemplarile, mis teda ennast hoiab. Järgmised kaks direktiivi on samaväärsed:

theMessage = getParameter("message");

theMessage = this.getParameter("message");
Tavaliselt kasuatatakse lühemat vormi, kuid mõnikord läheb vaja ka this abil viitamist.

Sündmused (events)

HelloWeb2 viimane osa on meetod mouseDrag(), mille abil me saame informatsiooni hiirelt. Iga kord, kui kasutaja teostab mingi tegevuse, nagu näiteks klahvivajutus klaviatuurilt, hiire liigutamine, puudutustundliku ekraani puudutamine, genereerib Java sündmuse. Sündmus esitab tehtud tegevust, see sisaldab informatsiooni tegevuse kohta, nagu näiteks tegevuse aeg ja koht. Sündmused võivad mingis programmis olla seotud graafilise kasutajaliidese osadega (GUI - Graphical User Interface). Näiteks klahvivajutuse tulemusel võib tekstikastikesse ilmuda täht, hiire liigutamisel mingile GUI osale võib muutuda kursori kuju jne.

Iga piirkond ekraanil kuulub mingile GUI komponendile. Iga komponent reageerib erinevat tüüpi sündmustele. GUI komponendid on samuti objektid. Kui toimub sündmus, siis teeb Java kindlaks, millisele objektile see sündmus kuulub ja saadab sündmuse sobivale objektile. Informatsiooni toimunud sündmuse kohta hoitakse klassi java.awt.Event eksemplaris. Sündmus saadakse kätte, kutsudes välja meetodi vastuvõtvas objektis. Event tüüpi objekt antakse argumendina sellele meetodile.

Sündmustest räägitakse täpsemalt peatükis 10. Meie näites on ainult üks komponent, kuhu sündmuseid saadetakse.

  public boolean mouseDrag( Event evt, int x, int y ) {
    messageX = x;
    messageY = y;
    repaint();
    return true;
  }
Kui hiirega lohistatakse, kutsub Java korduvalt välja meetodit mouseDrag(), et uuendada objekti asukohta. Meetodi mouseDrag() esimene argument on tüüpi Event. Me omistame selle muutujale evt. See sisaldab muu hulgas ka järgmist informatsiooni: sündmuse tüüp (hiirega lohistamine), millise komponendiga see juhtus (meie rakend) ja sündmuse x,y koordinaadid (jooksev kursori positsioon). Meetodi mouseDrag() kaks viimast argumenti on tüüpi integer ja sisaldavad hiirekursori x ja y koordinaate.

Võib tunduda imelik, et milleks on üldse vaja meetodit mouseDrag() ja milleks on vaja panna koordinaate x ja y eraldi muutujatesse - Event tüüpi objektis on ju kogu informatsioon olemas. Vastus sellele on, et mouseDrag() on programmeerimismugavus (programming convenience). Seda, kas sündmusi on tekkinud, kontrollib madalama taseme meetod. See meetod kontrollib selle sündmuse tüüpi ja saadab selle edasi spetsiifilisemale meetodile. Siinkohale ei vaeva me pead meetodi mouseDrag() argumentidega ja kasutame lihtsalt x ja y koordinaate meie töö tegemiseks.

Meetod mouseDrag() teeb kolme asja. Esiteks eksemplari muutujatele messageX ja messageY omistatakse hiirekursori koordinaadid. Nüüd, olles koordinaate muutnud, tuleks lasta HelloWeb2 -l ennast uuesti joonistada. See võib esmapilgul lihtne tunduda - kasutame meetodit paint(), kuid lähemal vaatlemisel selgub, et meil ei ole anda meetodile paint() Graphics tüüpi parameetrit. Mida teha?

Meetod repaint()

Me võime kasutada klassi Applet meetodit repaint(), mille tulemusel võtab Java kavva meetodi paint() väljakutsumise esimesel võimalikul hetkel.

                                     --------------------
        Java Keskkond                I    Applet        I
                                     I                  I
        <-----------soov-------------I   repaint()      I
        ------Graphics kontekst----->Ipaint(Graphics g) I
                                     --------------------
Meetod repaint() on hea mitmel põhjusel: meetodite repaint() täitmiseks on eraldi lõim - seda tehakse teiste tegevustega paralleelselt. See kasulik näiteks akna kerimisel. Teiseks heaks omaduseks on see, et me ei pea meetodit paint() igale poole pikalt sisse kirjutama, piisab, kui kutsume välja meetodi repaint().

Lõpuks tagastab meie mouseDrag() meetod meetodile, mis ta välja kutsus, väärtuse true, millega me anname märku, et sündmusele vastavad tegevused on tehtud. Kui me tagastaksime siin false, siis ei muutuks ka midagi, kuid mõnes rakenduses kasutatakse tagastatud väärtusi.

Mõisted