JBuilder Käyttö Nörttitesti
Asennus Ikälaskuri Linkit
  «  1  2  3  4  5  6  7  8  »  
 
Toimintaa!

Ilman yhtään koodiriviä luomamme käyttöliittymä ei paljoa innosta. Aika on siis pistää laskuri laskemaan. Laskennalle oikea ajankohta on se, kun käyttäjä klikkaa lomakkeelle sijoittamaamme Laske-nappia. Ohjelmoimme siis tapahtumakäsittelijän, joka käynnistyy kun määritelty tapahtuma ilmenee: tässä tapauksessa kun nappiamme painetaan.

Siirry takaisin Design-välilehdelle ja klikkaa Laske-nappia lomakkeella. Valitse sitten Inspectorista Events-välilehti. Nyt näet listan siitä, mihin kaikkiin tapahtumiin nappi voi reagoida.

Näistä tarvitsemme kuitenkin vain ActionPerformed-käsittelijää, eli listan ensimmäistä. Sitä kutsutaan, kun nappia klikataan. Tuplaklikkaa ActionPerformed-kenttää, niin JBuilder hyppää kooditilaan ja avaa valmiiksi metodin rungon:

void LaskeNappi_actionPerformed(ActionEvent e) {
}

Toistaiseksi tapahtumakäsittelijämme ei tee mitään. Sitä kuitenkin kutsutaan, sillä samalla jbInit()-metodiin on ilmestynyt seuraava pätkä uutta koodia:

LaskeNappi.addActionListener(new java.awt.event.ActionListener() {
  public void actionPerformed(ActionEvent e) {
    LaskeNappi_actionPerformed(e);
  }
});

addActionListener-metodi lisää napille kuuntelijan, joka reagoi sen tapahtumiin. Metodille annetaan parametrina ilmentymä sisäluokasta, joka on eräs Javan erikoisominaisuus. Tässä kohtaa kuitenkin riittää, kun ymmärtää, että ylläoleva koodinpätkä kutsuu ActionPerformed-tapahtuman yhteydessä LaskeNappi_actionPerformed-metodia ja antaa sille parametriksi tapahtumarakenteen "e".

Näin siis tapahtuman klikkaaminen johtaa meidät juuri luotuun metodin runkoon. Ryhdytään siis tuumasta toimeen.


Syötteet talteen

Irtonaisina lomakkeella lojuvista syötteistä ei paljon iloa ole. Ne pitää saada metodiin talteen ja vielä muunnettua numeroiksikin (TextField-kentät sisältävät, kuten nimi kertoo, tekstiä). Varataan aluksi kolmelle kokonaislukumuuttujalle tilaa:

int vuosi, kuukausi, paiva;

Seuraavaksi on aika muuttaa kenttien sisältö numeeriseen muotoon. Javassa on onneksi tarjolla valmiiksi erittäin hyvät ja toimivat välineet moniin muunnoksiin, myös tähän. java.lang-pakkauksessa (joka muuten on käytössä ilman import-lausettakin) on luokka nimeltä Integer. Sillä on staattinen metodi nimeltä decode(), joka muuttaa parametrina saamansa merkkijonon numeromuotoon. Staattinen tarkoittaa sitä, ettei Integer-luokasta tarvitse luoda ilmentymää, vaan metodia voidaan kutsua suoraan luokan nimellä.

vuosi = Integer.decode(VuosiKentta.getText()); kuukausi = Integer.decode(KuukausiKentta.getText()); paiva = Integer.decode(PaivaKentta.getText());

getText()-metodi TextField-luokassa palauttaa siis kentässä olevan tekstisisällön.

Jos muunnoksessa tapahtuu virhe, esimerkiksi merkkijono sisältää vaikkapa kirjaimia, decode heittää poikkeuksen "NumberFormatException". Tätä varten rakennamme lisäksi pienen käsittelyrutiinin try-catch-lauseella. Samalla siirrämme edelliset lauseet try-lohkoon.


try {
  vuosi = Integer.decode(VuosiKentta.getText()).intValue();
  kuukausi = Integer.decode(KuukausiKentta.getText()).intValue();
  paiva = Integer.decode(PaivaKentta.getText()).intValue();
}
catch (NumberFormatException poikkeus) {
  // Virheellisiä parametrejä, eivät muutu merkkijonoiksi!
  TulosTeksti.setText("Virhe!");
  PaivaKentta.requestFocus();
  return;
}

Jos virhe siis tapahtuu, hyppää suoritus catch-lohkoon. TulosTeksti-kentän arvoksi asetetaan virhe, ja kursori siirretään requestFocus()-kutsulla takaisin PaivaKentta-nimiseen TextFieldiin. Tämän jälkeen tapahtumankäsittelijän suoritus lopetetaan return-lauseella.


Päiväys palasiksi

Kun syötteet on haettu, on aika käsitellä päiväyksiä. Tässä vaiheessa on tietysti vielä riski siitä, että käyttäjän syöttämät luvut ovat jotain täyttä puppua: päivä ei meidän kalenterissamme ole koskaan -4 tai kuukausi 13. Suoritetaan ensin virhetarkastelua:

int[] paiviaKuukaudessa = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if ((vuosi % 400 == 0) || ((vuosi % 4 == 0) && (vuosi % 100 != 0)))
    paiviaKuukaudessa[1] = 29;
if (paiva < 1 || kuukausi < 1 || kuukausi > 12 || paiva > paiviaKuukaudessa[kuukausi-1]) {
    // Epäkelpo päivä
    TulosTeksti.setText("Virhe!");
    PaivaKentta.requestFocus();
    return;
}

Ensimmäisellä rivillä luodaan taulukko, jossa on jokaisen kuukauden päivien määrä. Huomaa, että Javan taulukot lähtevät nollasta: tuo on siis itseasiassa taulukko 0-11, ja esimerkiksi lokakuun numero on 9. Seuraavat kaksi riviä käsittelevät erikoistapauksen: jos käyttäjän antama vuosi on karkausvuosi, helmikuussa kelpaa myös 29. päivä. Loppu koodista tarkistaakin vain erilaiset virhetilanteet, ja ongelman sattuessa tilanne puretaan kuten aiemminkin.

Nyt kun tieto on kelvollista, voimme ryhtyä laskemaan. Java.util-pakkauksessa on erittäin käytännöllinen Calendar-luokka, ja sen meikäläistä versiota vastaava aliluokka GregorianCalendar. Samassa pakkauksessa on myös yksittäistä päivämäärää ilmentävä Date-luokka.

Itse asiassa Calendaria tässä ohjelmassa tarvitaankin lähinnä sopivin arvoin alustetun Daten muodostamiseen. Calendar-luokka ottaa parametreikseen halutun päivämäärän, mutta pilkottuna palasiin. Tämähän sopii meille, sillä päivämäärä onkin jo valmiiksi kolmena kokonaislukuna (vuosi, kuukausi, päivä).

Aluksi on lisättävä uusi import-lause tiedoston alkupäähän:

import java.util.*;

ja sitten jatketaan metodin parissa:

Date syntymapaiva = new GregorianCalendar(vuosi, kuukausi-1, paiva).getTime(); Date nyt = new Date();

Ensimmäinen rivi muodostaa syntymapaiva-nimisen Date-olion. Se saa alkuarvonsa siten, että muodostetaan lennossa GregorianCalendar-olio (alkuarvoinaan käyttäjän syöttämä päivämäärä), jonka getTime()-metodi palauttaa Date-luokan uuden ilmentymän. Tämän hetken päivämäärä saadaan luomalla uusi Date ilman parametrejä. Huomaa, että GregorianCalendar käsittelee kuukausia 0-pohjaisesti: tammikuu on siis 0 ja joulukuu 11, joten kuukauden perään liitetään -1.

Date-luokalla on edelleen uusi getTime()-metodi, joka palauttaa Daten ilmaiseman kellonajan millisekunteina. Kun millisekunnit jakaa ensin tuhannella, niistä tulee sekunteja. Tämän jakaminen edelleen 86400:lla muuttaa luvun päiviksi. Javan lukutyyppi longiin mahtuu varmasti tarpeeksi, joten sijoitetaan vähennyslaskun tulos sellaiseen.

long ikaPaivina = (nyt.getTime()-syntymapaiva.getTime())/1000/86400;

Ja nyt voimmekin jo näyttää tuloksen:

TulosTeksti.setText(ikaPaivina+" päivää");

Näin ikälaskurimme on valmis. Lopputulos on kaukana täydellisestä ja kauniista, mutta se toimii - myös omilla WWW-sivuillasi!

JBuilder on tehnyt projektihakemistosi alle hakemistoon classes HTML-tiedoston, jolla voit testata applettia selaimessa. Ennen sen käyttöä kannattaa kuitenkin muuttaa HTML-tiedostoon ohjelmalomakkeen lopullinen leveys ja korkeus, jotta tulos näyttää siistimmältä.

  «  1  2  3  4  5  6  7  8  »