JBuilder-pikakurssi

 

 
 
 
 
 

LuK-tutkielma 28.5.1999
Markku Lehtinen
 
 
 

Jyväskylän yliopisto, tietotekniikan laitos


 


1. Malliohjelma

Luvun pääaiheet:

1.1 Yleistä JBuilderistä

JBuilder on visuaalinen Java-sovelluskehitin. Se on käytön kannalta varsin yhdenmukainen Borlandin muiden visuaalisten sovelluskehittimien, kuten Delphin ja C++Builderin kanssa. Ohjelman ulkoasun suunnittelu tapahtuu samalla tavalla asettelemalla komponentteja lomakkeille. Javassa komponentit ovat JavaBeaneja, joiden käsittely on hyvin pitkälle samanlaista Delphin komponenttien. Tässä esityksessä käytetäänkin näitä sanoja lähes synonyymeinä.


Kuva 1.1 JBuilder, esimerkkiohjelman suunnittelu

JBuilder 2.0 :ssa on vähemmän valmiita komponentteja kuin esim. Delphissä, vaikka niiden määrä onkin lisääntynyt 1.0-versiosta. Koodin organisointi ja synkronointi on varsin kehittynyttä ja parannettu leikekirjatoteutus helpottaa kehitystyötä. JBuilder 2.0 käyttää Java Developer Kit 1.1.6 ( JDK 1.1.6 )-versiota, joten sillä tuotetut ohjelmat eivät toimi ympäristöissä, joissa on käytössä aiempi JDK-versio.

1.2 Autolaskuri

Ensimmäisenä malliohjelmana teemme "autolaskurin". Sen kahta nappia painamalla voi lisätä joko henkilöautojen tai kuorma-autojen lukumäärää.


Kuva 1.2 Autolaskuri

1.2.1 Uuden sovelluksen luominen

  1. Käynnistä JBuilder.
  2.  Sulje mahdollisesti auki olevat projektit (File/Close All ).
  3.  Ensin luodaan sovellukselle projekti käyttäen ProjectWizardia. Käynnistä se tuplaklikkaamalla File/New-menusta avautuvasta New-ikkunasta Project-ikonia.
  4.  Täytä avautuneeseen dialogiin projektin tiedosto File-riville esim. c:\omat\autol\autolaskuri.jpr. Vaihda sen jälkeen projektille nimeksi Title-riville Autolaskuri. Paina lopuksi Finnish.
  5.  Projektin oletushakemistot kannattaa käydä vaihtamassa. Tämä onnistuu valitsemalla valikosta File/Project Properties . Vaihda sekä Source root -, että Output root -riveille sopiva polku, esim. c:\omat\autol\.
  6.  Käynnistä seuraavaksi ApplicationWizard valitsemalla File/New/Application. ApplicationWizard on kaksivaiheinen. Ensimmäisessä vaiheessa määritellään sovelluksen perusominaisuuksia. Tyhjennä Package-rivi (yksinkertaisuuden vuoksi; muutoin tuotettava koodi sijoitetaan tähän alihakemistoon ja tästä seuraa joitain hankaluuksia). Vaihda Class-riville nimeksi Autolaskuri. Paina Next-näppäintä.
  7.  Toisessa vaiheessa asetetaan sovelluksen päädialogiin ( Frame) liittyviä ominaisuuksia. Vaihda Class-riville nimeksi LaskuriFrame ja Frame Title -riville Autolaskuri. Paina taas lopuksi Finnish.
  8.  JBuilder on nyt luonut neljä eri tiedostoa: autolaskuri.jpr, autolaskuri.html, Autolaskuri.java ja LaskuriFrame.java.

1.2.2 Nappuloiden lisääminen

  1. Koko projektin pääikkunan ( AppBrowser) vasemmassa yläkulmassa on projektinhallintaikkuna. Valitse sieltä tiedosto LaskuriFrame.java, niin näet koodin, jonka JBuilder on luonut. Paina koodi-ikkunan alareunassa Design-välilehteä päästäksesi suunnittelemaan graafista ulkoasua.
  2. Valitse JBCL-työkaluvalikosta nappula ( ButtonControl,) klikkaamalla kuvaketta kerran
  3. Lisää nappula lomakkeeseen viemällä hiiri sinne minne haluat nappulan vasemman yläkulman ja paina vasen nappi alas. Siirrä hiiri oikean alakulman paikalle ja päästä nappi ylös. "Kahvoihin" tarttumalla voit vielä vaihtaa nappulan kokoa.
  4. Anna nappulalle nimeksi buttonContolHA.
  5. Vaihda nappulan tekstiksi Henkilöautoja (label-ominaisuus). Valitettavasti Javassa ei ole yksinkertaista tapaa yhdistää näppäinyhdistelmiä nappuloihin.
  6. Kopioi nappula leikepöydälle painamalla Ctrl-C. Liitä nappula paneelille leikepöydältä painamalla Ctrl-V. Anna uuden nappulan nimeksi buttonControlKA ja vaihda tekstiksi Kuorma-autoja.

1.2.3 Laskuriruutujen lisääminen

  1. Lisää lomakkeelle "laskuriruutu" nappulan alapuolelle käyttäen vakiotekstiä ( LabelControl,).
  2. Kun olet lisännyt tekstin, saat sen samanlevyiseksi kuin nappulankin valitsemalla molemmat aktiiviseksi ( shift+klikkaus hiiren vasemmalla napilla kumpaankin) ja sitten hiiren oikeasta näppäimestä aukeavasta menusta Same Size Horizontal. Huomaa, että koko muutetaan ensimmäisenä valitun objektin mukaiseksi.
  3. Nimeä teksti labelControlHA ja tekstiksi ( text) 0.
  4. Teksti saadaan ruudun oikeaan reunaan laittamalla alignment-ominaisuudeksi Right.
  5. Vaihda tekstin väriksi vaikkapa Blue (foreground-ominaisuus) ja taustaksi White (background-ominaisuus).
  6. Vaihda tekstin fontiksi vaikka Dialog Bold 18 ( font-ominaisuus).
  7. Muuta tekstiruudun korkeus vastaamaan fontin korkeutta.
  8. Kopioi tekstiruutu leikepöytää apuna käyttäen Kuorma-autoja-nappulan alle ja anna sille nimi: LabelKA.

1.2.4 Talletus

  1. Lisää vielä nappula, jonka nimeksi annat buttonContolNollaa ja tekstiksi Nollaa.
  2. Talleta projekti näppäinyhdistelmällä Alt-F v . tai valikkokäskyllä File/Save All .

1.2.5 Kääntäminen ja ajaminen

Ohjelma on nyt toimintakuntoinen, mutta se ei vielä tee mitään. Voimme kuitenkin kokeilla miltä valmis ohjelma näyttäisi:
  1. Käännä ja aja ohjelma painamalla F9

1.2.6 Ohjelmakoodin lisääminen

Koko ajan, kun komponentteja on aseteltu lomakkeelle JBuilder on lisännyt ohjelmakoodia LaskuriFrame-luokkaan ( class) tiedostoon LaskuriFrame.java. Tästä LaskuriFrame-luokasta luodaan olio Autolaskuri.java-tiedoston Autolaskuri-luokassa.Nappuloiden toiminnallisuutta vastaavan koodin lisääminen on ohjelmoijan tehtävä. Onneksi JBuilder tekee tästäkin suurimman osan:
  1. Tuplaklikkaa Henkilöautoja-nappulaa. Tällöin aukeaa koodi-ikkuna, jossa on valmiina Java-kielinen tapahtumankäsittelijän esittely tapahtumalle, joka tulee kun painetaan nappulaa nimeltä buttonControlHA:
  2. void buttonControlHA_actionPerformed(ActionEvent e) { }
  3. Kursori on valmiina paikassa, johon oma koodi kirjoitetaan. Halutaan, että nappulaa painettaessa labelControlHA:ssa oleva lukema lisääntyy yhdellä. Komponenttien ominaisuuksia voi muuttaa vain niihin tarkoitetuilla metodeilla, joista tässä käytetään metodia setText(). Teksikentän teksti muutettava ensin numeeriseksi, koska tekstiä ei voi numeerisesti lisätä. Siispä kirjoitamme koodin
  4. labelControlHA.setText(""+(Integer.parseInt(labelControlHA.getText())+1));
  5. Koodi kannattaa saman tien laittaa leikekirjaan, koska se tulee lähes samanlaisena nappulaan buttonControlKA.
  6. Lisää vastaava koodi oikein muutettuna nappulaan buttonControlKA. Huom! Jos et edellä huomannut laittaa koodia leikekirjaan, löytyy edellinen koodi samasta koodi-ikkunasta hieman ylempää ja voit hakea sen kuin missä tahansa editorissa.
  7. Lisää vielä koodi nappulaan buttonControlNollaa. Nyt koodiksi riittää
  8. labelControlHA.setText("0");labelControlKA.setText("0");
  9. Käännä ja aja ohjelma.

1.2.7 Valmis ohjelma

Seuraavana vielä listaukset valmiin malliohjelman eri tiedostoista hakemistossa autol. ( autolaskuri.jpr ei ole mukana). Ensimmäisenä on JBuilderin luoma kuvaus projektista.

 
autolaskuri.html - projektin kuvaus
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>Jbuilder Project autolaskuri.jpr</TITLE>
</HEAD>
<BODY>
<H1>Project Notes</H1>
<HR>
<FONT SIZE=+1>
<STRONG>Project:  </STRONG>Autolaskuri<BR>
<STRONG>Author: Markku Lehtinen</STRONG><BR>
<STRONG>Company: </STRONG><BR>
<STRONG>Description: </STRONG><BR>

<HR>
<STRONG>Things to do...</STRONG><BR>
</FONT>
<UL>
<!-- Edit this section to keep track of your to do items -->
<LI>Item 1
<LI>Item 2
</UL>
</BODY>
</HTML>

Autolaskurin pääluokka sijaitsee autolaskuri.java-tiedostossa, jossa myös on main-metodi
 
Autolaskuri.java - autolaskurin pääluokka
import com.sun.java.swing.UIManager;

public class Autolaskuri {
  boolean packFrame = false;

  //Construct the application

  public Autolaskuri() {
    LaskuriFrame frame = new LaskuriFrame();
    //Validate frames that have preset sizes
    //Pack frames that have useful preferred size info, e.g. from their layout
    if (packFrame)
      frame.pack();
    else
      frame.validate();
    frame.setVisible(true);
  }
//Main method

  public static void main(String[] args) {
    try  {
      UIManager.setLookAndFeel(new com.sun.java.swing.plaf.windows.WindowsLookAndFeel());
      //UIManager.setLookAndFeel(new com.sun.java.swing.plaf.motif.MotifLookAndFeel());
      //UIManager.setLookAndFeel(new com.sun.java.swing.plaf.metal.MetalLookAndFeel());
    }
    catch (Exception e) {
    }
    new Autolaskuri();
  }
}

LaskuriFrame.java-tiedostossa on varsianinen graafinen toteutus. Seuraavassa lomakkeen listauksessa tummennetut osat ovat niitä, joita on muutettu AppBrowserissa. JBuilderissä ei ole erikseen resurssitiedostoja, vaan kaikki komponenttien ominaisuudet asetetaan ja luetaan omilla metodeillaan.
 
LaskuriFrame.java - Varsinasen käyttöliittymän totettava luokka
import java.awt.*;
import java.awt.event.*;
import borland.jbcl.control.*;
import borland.jbcl.layout.*;

public class LaskuriFrame extends DecoratedFrame {

  //Construct the frame
  BorderLayout borderLayout1 = new BorderLayout();
  XYLayout xYLayout2 = new XYLayout();
  BevelPanel bevelPanel1 = new BevelPanel();
  ButtonControl buttonControlHA = new ButtonControl();
  ButtonControl buttonControlKA = new ButtonControl();
  LabelControl labelControlHA = new LabelControl();
  LabelControl labelControlKA = new LabelControl();
  ButtonControl buttonControlNollaa = new ButtonControl();

  public LaskuriFrame() {
    try  {
      jbInit();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

//Component initialization

  private void jbInit() throws Exception  {
    this.setLayout(borderLayout1);
    this.setSize(new Dimension(273, 201));
    this.setTitle("Autolaskuri");
    buttonControlHA.setLabel("Henkilöautoja");
    buttonControlHA.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        buttonControlHA_actionPerformed(e);
      }
    });
    buttonControlKA.setLabel("Kuorma-autoja");
    buttonControlKA.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        buttonControlKA_actionPerformed(e);
      }
    });
    labelControlHA.setBackground(Color.white);
    labelControlHA.setFont(new Font("Dialog", 1, 18));
    labelControlHA.setForeground(Color.blue);
    labelControlHA.setAlignment(Label.RIGHT);
    labelControlHA.setText("0");
    labelControlKA.setAlignment(Label.RIGHT);
    labelControlKA.setForeground(Color.blue);
    labelControlKA.setFont(new Font("Dialog", 1, 18));
    labelControlKA.setBackground(Color.white);
    labelControlKA.setText("0");
    buttonControlNollaa.setLabel("Nollaa");
    buttonControlNollaa.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        buttonControlNollaa_actionPerformed(e);
      }
    });
    bevelPanel1.setLayout(xYLayout2);
    this.add(bevelPanel1, BorderLayout.CENTER);
    bevelPanel1.add(buttonControlKA, new XYConstraints(140, 21, 100, 26));
    bevelPanel1.add(buttonControlHA, new XYConstraints(22, 21, 100, 26));
    bevelPanel1.add(labelControlHA, new XYConstraints(22, 57, 100, -1));
    bevelPanel1.add(labelControlKA, new XYConstraints(140, 57, 100, -1));
    bevelPanel1.add(buttonControlNollaa, new XYConstraints(94, 113, 74, 31));
  }

  void buttonControlHA_actionPerformed(ActionEvent e) {
    labelControlHA.setText(""+(Integer.parseInt(labelControlHA.getText())+1));
  }

  void buttonControlKA_actionPerformed(ActionEvent e) {
    labelControlKA.setText(""+(Integer.parseInt(labelControlKA.getText())+1));
  }
  void buttonControlNollaa_actionPerformed(ActionEvent e) {
   labelControlHA.setText("0");
   labelControlKA.setText("0");
  }

}

Tehtävä 1.1 Polkupyörät Lisää ohjelmaan myös polkupyörien laskeminen.

1.3 Muita komponentteja

JavassaDelphin ja C++Builderin komponetteja vastaavat JavaBeanit..JBuilderissa ei kuitenkaan ole valmiina niin laajaa komponenttikirjastoa kuin esim. Delphissä. Sen sijaan omia beaneja on varsin helppo luoda JBuilderin tarjoamilla työkaluilla. Seuraavissa esimerkeissä käytetään itsetehtyjä beaneja, koska vastaavia toimintoja ei ole JBuilderissä niin yksinkertaisesti toteutettavissa kuin tämän luvun tarkoituksena on. Seuraavia toimenpiteitä varten tarvitaan omat.jar-niminen tiedosto, joka sisältää nämä beanit. Tämän tiedoston voi hakea kirjan alussa mainitusta paikasta. Lisäksi tarvitset auton kuvaa varten tiedoston hauto.gif. Kuva on gif-muodossa, koska Javassa on suora tuki vain gif- ja jpg-tyyppisille kuville. Kopioi auton kuva projektitiedostoon ennen seuraavaa vaihetta.

1.3.1 Itsetehdyn beanin lisääminen työkaluvalikkoon

  1. Valitse työkaluvalikosta Others -välilehti. Klikkaa välilehden päällä hiiren oikeaa näppäintä. Saat Properties-valikon.
  2.  Valitse välilehti Add from Archive . Paikallista Browse näppäimellä omat.jar -tiedosto, jonka olet hakenut. Valitse ylemmästä valintaikkunasta package nimeltä omat.image. Nyt alavalikossa näkyy bean nimeltä omat.image.ImageBean.
  3. Valitse ko. bean ja paina Install-nappulaa. Tee sama omat.timer.TimerBeanille Voit nyt käyttää beaneja aivan kuten muitakin työkaluvalikon komponentteja, jotka todellisuudessa ovat itsekin JavaBeaneja.

1.3.2 TimerBean - ajastetut tapahtumat

Lisätään lomakkeelle vaikkapa aluksi auton kuva, joka ajaa ruudun vasemmasta laidasta oikeaan laitaan.
  1. Lisää juuri haettu ImageBean-komponentti ruudun vasempaan alalaitaan. Komponentin koon ja paikan saat määrättyä samoin kuin aiemmin nappulaa lisättäessä.
  2. Jos et äsken kopioinut auton kuvaa projektihakemistoon, tee se nyt. Klikkaa ImageBean-komponenttia ja laita siihen ominaisuudeksi imageName:hauto.gif. Kuva näkyy paneelilla, kun ohjelmaa ajetaan. Huom. Käytä vain suhteellista osoitusta, koska varsinkin Applet-tyyppisissä sovelluksissa saattaa tulla ongelmia.
  3. Vaihda beanin nimeksi vaikkapa imageBeanHA. Jotta auton kuva liikkuisi, tulee ImageBean-olion paikkaa muuttaa tietyn väliajoin. Tietyin aikavälein tapahtuvia tapahtumia saadaan TimerBean-komponentilta.
  4. Lisää lomakkeelle mihin tahansa kohtaan TimerBean-komponentti (löytyy siis Others-sivulta). Paikalla ei ole väliä, koska bean sijoitetaan komponettihierarkiaan kohtaan Others. Komponettihierarkia näkyy AppBrowserin vasemmalla sivulla, kun ollaan Design-tilassa.
  5. Vaihda ajastimen nimeksi vaikkapa TimerBeanHA
  6. Vaihda tapahtumaväliksi ( timeSlice) esim 100 (100 ms). Huom! Tapahtumaväli täytyy alustaa positiiviseksi luvuksi, jotta ajastin lähtee käyntiin.
  7. Tuplaklikkaa Events-sivulla timerActionia ja paina Enter. Kirjoita tapahtuman-käsittelijään seuraava koodi.
  8. void timerBeanHA_timerAction(TimerEvent e) {
      imageBeanHA.setLocation(imageBeanHA.getLocation().x + 1,
                              imageBeanHA.getLocation().y);
    }
  9. Huom! Java-komponenttien päivitys ei ole ilmeisesti tehty tällaista varten, joten liikkuva kuva saattaa välkkyä ja käyttäytyä välillä hieman oudosti.
Tehtävä 1.2 Edestakaisin Muuta ohjelmaa siten, että auton kuva kulkee ruudussa edestakaisin.

1.3.3 Menut

Lisätään ohjelmaan vielä päämenu.
  1. Lisää lomakkeelle MenuBar-komponentti ( AWT-sivu). Menu syntyy komponentti-hierarkiaan kohtaan Menu.
  2. Tuplaklikkaa Menu-oliota komponenttihierarkiassa.
  3. Kirjoita seuraava valikkojärjestelmä: (Huomaa, että Javassa ei voi &-merkillä aikaansaada pikavalintaa)
  4. File Options Help
    Exit Colors  About
  5. Laita vielä lisäksi Exit-kohtaan pikavalinta Ctrl-X. ( Propeties - shortcut )
  6. AktivoiExit-menuvalinnan Events-sivulta actionPerformed ja lisää tapahtumaksi koodi
  7. void menuItemExit_actionPerformed(ActionEvent e) {
      System.exit(0);
    }

1.3.4 Valmiit lomakkeet

JBuilderissä on valmiina joukko yleisimpiä dialogeja, kuten tiedostodialogi, fonttien valinta, värin valinta sekä viestidialogi.Lisäämme seuraavaksi mahdollisuuden taustavärin vaihtamiseksi.
  1. Lisää komponenttihierarkiaan väridialogi ( JBCL Containers-sivu).
  2. Laita dialogin nimeksi vaikkapa colorChooserTausta.
  3. Aseta dialogin frame-ominaisuus: this.
  4. Lisää Options-menun Colors-kohdan tapahtumaksi koodi:
  5. void menuItemColors_actionPerformed(ActionEvent e) {
      colorChooserTausta.show();
      if (colorChooserTausta.getResult() == ColorChooser.OK)
        bevelPanel1.setBackground(colorChooserTausta.getValue());
    }
Tehtävä 1.3 Muidenkin komponenttien värin vaihto Muuta ohjelmaa siten, että voit muuttaa kaikkien muidenkin komponettien värin (voit käyttää samaa dialogia kaikille komponenteille).

1.3.5 Omat dialogit

Oikeassa ohjelmassa on harvoin vain yksi ikkuna. Lisäämme esimerkin vuoksi vielä ohjelmaamme itse tehdyn About-dialogin: ( About-dialogin saisi tehtyä myöskin automaattisesti. )
  1. Ensin on luotava dialogille oma Frame. Tämä onnistuu valitsemalla valikosta File|New - New|Frame . Kirjoita package-riville vaikkapa dialogit (JBuilder 2.0:ssa on pakko antaa jokin nimi tähän. Käytännössä tämä tarkoittaa sitä, että generoitavat tiedostot sijoitetaan annetun nimen mukaiseen alihakemistoon.) Luokan nimeksi anna AboutFrame.
  2. Dialogin luonti hoituu valitsemalla valikosta File|New - New|Dialog .
  3. package-riville käy jälleen alihakemisto dialogit. Vaihda luokan nimeksi AboutDialog.
  4. Tarkista, että About-dialogin paneelin ( panel1) ominaisuus layout on asennossa XYLayout. JBuilderissä ei monirivistä vakiotekstiä, joten lisää vakiotekstejä ( LabelControl) joiden nimiksi laitat vaikkapa LabelAbout1, ... 2 jne. Tekstiksi sitten mikä tahansa ohjelman toimintaa yms. kuvaavaa tekstiä.
  5. Lisää vielä haluamiasi koristeita, kuten esim. kuvia (vrt. liikkuvan auton lisääminen).
  6. Lisää vielä nappula, jonka nimeksi annat buttonControlOK ja tekstiksi OK.
  7. Lisää OK-nappulan koodiksi:
  8.  void buttonControlOK_actionPerformed(ActionEvent e) {
         this.setVisible(false);
     }
  9. Dialogi on nyt valmis, mutta siihen ei viitata varsinaisesta lomakkeesta. Lisää LaskuriFrame.java-tiedostoon:
  10.    import dialogit.*;

     public class LaskuriFrame extends DecoratedFrame {
         AboutFrame  aboutFrame = new AboutFrame();
         AboutDialog aboutDialog = new AboutDialog(aboutFrame,
                                                 "Tietoja Autolaskurista",false);
       ...

     }

  11. Lisää menunvalintaan About seuraava koodi:
  12.  void menuItemAbout_actionPerformed(ActionEvent e) {
         aboutDialog.show();
     }
  13. Kokeile ohjelmaa.


Tehtävä 1.4 Modaalinen dialogi Muuta koodi AboutDialog aboutDialog = new ... muotoon:
 AboutDialog aboutDialog = new AboutDialog(aboutFrame,"Tietoja Autolaskurista",true);
 Mitä eroa on nyt ohjelman toiminnassa?
Tehtävä 1.5 Liikkuva auto myös toisessa dialogissa Lisää liikkuva auto myös About-dialogiin.

1.4 Ohjelmakoodin korjailu

JBuilderissä on varsin kehittynyt ohjelmakoodin editiointi. Seuraavassa muutamia piirteitä:
  1. JBuilderissä ohjelmakoodi pysyy synkronissa, muutettiinpa komponenttien ominaisuuksia joko Source- tai Design-tilassa (teksti- tai suunnittelutilassa). Tosin tässäkin on rajoituksensa. Älä muuta komponentti-olion nimeä tekstitilassa, koska joudut tekemään muutoksen jokaiseen olion esiintymiseen ohjelmakoodissa. Dynaamisesti ajon aikana luotavat komponentit eivät tietenkään näy suunnitteluikkunassa.
  2. Source-tilassa AppBrowserin vasemmassa reunassa toimii reaaliaikainen koodinjäsentäjä. Jäsentimellä voidaan paikallistaa haluttuja elementtejä helposti. Jäsentimellä voidaan liikkua myös luokkahierarkiassa. Kokeile sitä esimerkiksi valitsemalla LaskuriFrame.javaSource-tilaan ja tuplaklikkaa DecoratedFrame-solmua. Tästä voit jatkaa luokkahierarkiaa ylöspäin.
  3. Jäsentimen avulla voi myös saada dokumenttitietoa käsiteltävänä olevasta luokasta, mikäli dokumentit on asennettu järjestelmään. Kokeile ensin kuten edellä ja valitse sitten Doc-tilan.

1.5 Muut tapahtumat

1.5.1 Saman tapahtuman käyttö toisessa komponentissa

Tapahtuman käsittelijän koodi on voitu kirjoittaa tuplaklikkaamalla komponenttia. Näin voidaan kirjoittaa kuitenkin vain komponentin oletustapahtuman käsittelijän. Kullakin komponentilla on lukuisia muitakin tapahtumia. Nämä muut tapahtumat löytyvä Component Inspectorissa Events-sivulta. Seuraavassa kuvassa on esimerkki buttonControlHA:n mahdollisista tapahtumista:


Kuva 1.3 Events-sivu

Tapahtuman nimi päästään kirjoittamaan tuplaklikkaamalla tapahtuman nimen paikkaa (tai siinä jo olevaa nimeä). Itse koodia päästään lisämään tuplaklikkaamalla toisen kerran tai painamalla enter. Tapahtumakäsittelijä voidaan laittaa myös samaksi jonkin toisen tapahtuman kanssa jolla on sama tapahtumatyyppi (esim. molempien tyyppi on mouseEvent).

Tehtävä 1.6 Laskenta tapahtumaan myös laskurista Muuta ohjelmaa (kirjoittamatta lisää koodia) siten, että myös laskurikentän LabelHA tai LabelKA painaminen lisää vastaavaa laskuria. Laita vielä liikkuvan kuvan painaminen lisäämään henkilöautojen lukumäärää.

1.5.2 Vedä ja pudota (drag and drop, DaD)

JavaSoft on määritellyt Drag and drop -konseptin, mutta sitä ei ole vielä toteutettu JDK 1.1 :ssä.

1.6 APPLET-tyyppinen Java-ohjelma

Tähän mennessä on saatu aikaiseksi Java-sovellus, joka toimii vain JDK:n mukana tulevan Java-tulkin alaisuudessa. Entäpä, jos halutaan siirtää autolaskuri sellaiseen muotoon, että sitä voidaan ajaa vaikkapa jollain HTML-selaimella? Tätä varten on olemassa Applet-tyyppiset Java-ohjelmat. Tarkastellaan seuraavaksi, kuinka autolaskuri voidaan muuttaa Applet-tyyppiseksi.
  1. Luodaan ensin uusi Appletti (valikkokäskyllä File|New - New|Applet ). Tämä tulee toimimaan alustana LaskuriFramelle, joka on jo saatu aikaiseksi.
  2. Tyhjennä jälleen package-rivi ja vaihda luokan nimeksi LaskuriApplet.
  3.  Paina kaksi kertaa Next-näppäintä, jolloin siirryt vaiheeseen 3/3. Vaihda kohtiin Title ja Name vaikka LaskuriApplet. Paina lopuksi Finnish.
  4.  Etsi käsille vanha päätiedosto Autolaskuri.java Kopioi sieltä seuraavat alueet leikepöytään.
  5. public class Autolaskuri {
      boolean packFrame = false;

      //Construct the application
      public Autolaskuri() {
        LaskuriFrame frame = new LaskuriFrame();
        //Pack frames that have useful preferred size info, e.g. from their layout
        //Validate frames that have preset sizes
        if (packFrame)
          frame.pack();
        else
          frame.validate();
        frame.setVisible(true);
      }

      //Main method
      static public void main(String[] args) {
        new Autolaskuri();
      }

  6. Liitä nämä rivit LaskuriApplet.java-tiedostoon:
  7. //Construct the applet
      public LaskuriApplet() {
        LaskuriFrame frame = new LaskuriFrame();
        frame.validate();
        frame.setVisible(true);
      }
  8. LaskuriApplet.html pitää valita projektin aktiiviseksi ohjelmaksi projektin ominaisuuksista ( File|Project Properties ). Vaihda LaskuriApplet.html aktiiviseksi kohtaan Run|Debug|Default runnable file . Aja ohjelma ( F9).
  9. Java-applettejen ajamiseen tarvitaan erillinen ohjelma, jota kutsutaan Appletvieweriksi. Tälle ohjelmalle täytyy antaa parametrina html-tiedosto, jossa on kerrottu <APPLET> -tagilla, mikä appletti halutaan suorittaa. Suorituksen aikana ensin ruutuun ilmestyy Appletviewer ja sen jälkeen vasta Autolaskuri. Seuraavassa on osa LaskuriApplet.html-tiedostoa.
  10. <APPLET
      CODEBASE = "."
      CODE     = "LaskuriApplet.class"
      NAME     = "AutolaskuriApplet"
      WIDTH    = 400
      HEIGHT   = 300
      HSPACE   = 0
      VSPACE   = 0
      ALIGN    = middle
    >

1.7 Java-ohjelmien siirtämisestä eri käyttöjärjestelmiin

Java-kielen eräs tärkeimpiä ominaisuuksia on sen käyttöjärjestelmäriippumattomuus. Periaatteessa samat ohjelmat pyörivät eri käyttöjärjestelmissä sellaisenaan. Hankaluuksia saattaa kuitenkin aiheuttaa erilaiset graafiset ympäristöt. Tämän vuoksi Javan perusmäärittelyssä ei ole koordinaatteihin perustuvaa komponenttien käsittelyä, vaan kaikki komponenttien asettelut annetaan järjestelmän tehtäväksi tietyn layoutin mukaan. Tämän esimerkin autolaskurissa on käytetty JBuilderin oletus-layoutia, XYLayoutia, joka ei kuitenkaan sovellu käytettäväksi ohjelmissa, joita halutaan siirtää käyttöjärjestelmien välillä. Tämän tähden XYLayoutia pitäisi käyttää ainoastaan sovelluksen kehitysvaiheessa. Lisäksi luokkakirjastojen siirtäminen tuottaa erilaisia ongelmia ja niihin on kehitetty erilaisia ratkaisuja. Seuraavassa esitellään muutamia tärkeimpiä siirtämiseen liittyviä asioita.

1.7.1 CLASSPATH-ympäristömuuttuja

Java-luokkien käytössä oleellisen tärkeä asia on ympäristömuttuja CLASSPATH. Sen avulla Java-tulkki osaa löytää tarvittavat luokkakirjastot järjestelmästä. Seuraavassa on esimerkki CLASSPATH:in käytöstä Windows NT :ssä.
  1. Avaa projektin ominaisuudet (klikkaa oikealla näppäimellä autolaskuri.jpr:ää)
  2.  Paina Libraries-nappia saadaksesi näkyville luokkakirjastojen polkujen määrittelyt. Tarkista, että oikealla olevassa ikkunassa on valittuna JBCL 2.0 . Kopioi leikepöytään (harmaana oleva) Class Path -rivi.
  3.  Käynnistä Windowstin Control Paneli sta System-ohjelma ja sieltä Enviroment-sivu.
  4.  Kirjoita Variable-riville CLASSPATH ja liitä leikepöydän sisältö Value-riville. Laita vielä polun alkuun oletushakemisto lisäämällä .; Paina Set-näppäintä ja lopuksi Apply-näppäintä.
  5.  Lisää vielä PATH-muuttujaan polku JBuilder\Java\bin -hakemistoon samalla tavalla. Huomaa, että tällä lailla asetukset tallentuvat pysyvästi järjestelmään!
  6. Käynnistä cmd-komentotulkki. Jos et halua muuttaa järjestelmän asetuksia, voit muuttaa ympäristömuuttujien arvoja myös komentotulkista set-käskyllä. Tällöin asetukset häviävät, kun komentotulkista poistutaan.
  7. Siirry projektihakemistoon ja kirjoita: appletviewer LaskuriApplet.html .
UNIX:ssa CLASSPATH asetetaan hieman erilailla riippuen komentotulkista. Matematiikan laitoksen jane-koneessa se tapahtuu esimerkiksi seuraavasti: export CLASSPATH=.:~/java:~/classes/jbcl.zip:... . Tämän jälkeen voidaan Java-sovelluksia ajaa yhtälailla UNIXssa, kunhan vain kaikki tarvittavat luokkakirjastot on määritelty CLASSPATH:issa ( JBuilder 2.0 :n käyttämiä ovat mm: jbcl2.0.jar, jgl3.1.0.jar ja swingall.jar). Sovellukseen erikseen ladattavien tiedostojen, kuten kuvien ja äänien käytössä saattaa olla hankaluuksia.

1.7.2 Deployment Wizard

JBuilderillä on helpoin tapa siirtää Java-ohjelmia eri järjestelmiin käyttäen Deployment Wizardia .Ominaisuuksia: Pakataan autolaskuri jar-tiedostoon:
  1. Talleta kaikki tiedostot ja käännä ohjelma aktivoimalla autolaskuri.jpr ja näppäilemällä Ctrl-F9.
  2.  Käynnistä Deployment Wizard Tools-menusta.
  3.  Muuta tiedoston nimi esim. laskuri.jar. Huomaa, että tiedoston pitää tulla samaan hakemistoon, missä LaskuriApplet.html on.
  4. Rastita kohdat JBCL ja JGL. Tämä tarkoittaa sitä, että Borlandin omista luokkakirjastoista otetaan mukaan pakettiin tarpeelliset luokat. Kohdejärjestelmässä ei siis tarvitse olla näitä kirjastoja asennettuna.
  5. Käynnistä Wizard painamalla Finnish.
  6.  LaskuriApplet.html-tiedostoon täytyy nyt lisätä seuraavastaa:
  7. ...

    <APPLET
      CODEBASE = ""
      CODE     = "Autolaskuri.class"
      ARCHIVE  = "laskuri.jar"
      WIDTH    = 400
      HEIGHT   = 300
      HSPACE   = 0
      VSPACE   = 0
      ALIGN    = Middle
    >
    ...

  8. Käynnistä komentotulkki, siirry projektihakemistoon ja aseta ympäristömuuttuja käskyllä set CLASSPATH=laskuri.jar.
  9. Kokeile laskurin toimintaa appletviewer LaskuriApplet.html .
 Autolaskurin pitäisi toimia nyt myös UNIX-koneissa, esim. janessa. Kopioi laskuri.jar, LaskuriApplet.html ja kuvatiedostot sinne johonkin hakemistoon, aseta CLASSPATH osoittamaan jar-tiedostoon ja kokeile appletviewer LaskuriApplet.html .

2. Javan perusominaisuuksia

Luvun pääaiheet:

2.1 Lyhyt johdanto Javaan

Java on kehitetty C++ -kielen pohjalta, joten syntaksiltaan se on sitä hyvin lähellä. Näin on pyritty luomaan tutun oloinen kieli, jossa kuitenkin olisi C++:n ongelmia korjattu. Seuraavassa joitan erityisominaisuuksia:  Aloitetaan rakenteen selvittäminen lyhyellä konsoliohjelmalla, joka lukee kaksi kokonaislukua ja tulostaa niistä suuremman, lukujen keskiarvon ja luvut suuruusjärjestyksessä. Muuttujien arvot vaihdetaan pääohjelmassa, koska Javan parametrien välitys tekee swap-tyyppisen aliohjelman hankalaksi toteuttaa (ks. parametrien välitys -esimerkkiä)
 
Perus.java - Java perusrakenne
public class Perus {

  static public void main(String[] args) {
    int a,b;

    System.out.println("Anna kaksi lukua rivinvaihdolla erotettuna");

    a = (int) Ali.readValue();  b = (int) Ali.readValue();

    System.out.println("Suurempi luvuista on " + Ali.bigger(a,b));
    System.out.println("Lukujen keskiarvo on " + Ali.average(a,b));

    if (a > b) {
      int apu = a; a = b; b = apu;
      System.out.println("Luvut järjestyksessä ovat " + a + " " + b);
    } else
      System.out.println("Luvut olivat järjestykseeä");
   }
}

2.2 Parametrin välitys

Edellisen esimerkin aliohjelmat on kirjoitettu omaan tiedostoonsa. Tiedoston tulee sijaita projektihakemistossa, josta Java-kääntäjä osaa etsiä sitä automaattisesti tarpeen vaatiessa. Aliohjelmat voidaan määritellä package-käskyn avulla myös yleiskäyttöisiksi aliohjelmakirjastoiksi. Tällöin aliohjelma pitää ottaa käyttöön import-käskyllä pääohjelmatiedoston alussa. Seuraavassa esimerkissä tällä käskyllä otetaan käyttään Javan syöttöön ja tulostukseen liittyvä aliohjelmakirjasto.
 
Ali.java - aliohjelmat
import java.io.*;

public class Ali {
  static public double readValue() {
    StreamTokenizer st = new StreamTokenizer(
                            new BufferedReader(
                               new InputStreamReader(System.in)));
    st.parseNumbers();

    try {
      st.nextToken();
    } catch (IOException e){}

    return st.nval;
  }

  static public int bigger(int a, int b) {
    if ( a > b ) return a;
    return a;
  }

  static public double average(int a, int b) {
    return (a+b)/2.0;
  }
}

Luodaan uusi luokka (jompaan kumpaan tiedostoon):
class Apu_int {
  int luku;

  Apu_int(int arvo) { luku = arvo; }

  public void aseta(int arvo) { luku = arvo; }
  public int arvo() { return luku; }

  static public void swap(Apu_int a, Apu_int b) {
    int apu;
    apu = b.arvo(); b.aseta(a.arvo()); a.aseta(apu);
  }
}

ja lisätään pääohjelmaan rivit:
 
Apu_int bi = new Apu_int(b); Apu_int ai = new Apu_int(a);
Apu_int.swap(ai,bi);
a = ai.arvo(); b = bi.arvo();
Se, että onko tällaisessa mitään järkeä, on eri kysymys! Koska luokan lisäksi taulukko välitetään call-by-reference-muodossa myös sitä voisi käyttää swap-toteutukseen.

2.2.1 Silmukat ja taulukot

Seuraavassa esimerkissä on ohjelma, joka ensin tekee viisipaikkaisen kokonaislukutaulukon:
 
0 1 2 3 4
0 3 6 9 12

 Sitten ohjelma laskee montako taulukon alkiota voidaan ottaa mukaan, ilman että summa ylittää vielä 10. Lopuksi tulostetaan ko. alkiot takaperin:
 
3 lukua mahtuu alle 10 näiden summa on 9
Luvut on: 6 3 0 
Silmu.java - esimerkki silmukoista ja taulukoista
public class Silmu {
  final static int TKOKO = 5,RAJA = 10;

  static void alusta(int[] luvut, int n, int kasvu)
  {
    int luku = 0, iraja = ( n > luvut.length ? luvut.length : n );
    for(int i = 0; i < iraja; i++) {
      luvut[i] = luku;
      luku += kasvu;
    }
  }

  static int montako_mahtuu(int[] luvut, int n, int raja)
  {
    int i = 0, summa = 0, iraja = ( n > luvut.length ? luvut.length : n );
    do {
      summa += luvut[i];
    } while ( summa < raja && ++i < iraja);
    return i;
  }
 
 

  static int summaa(int[] luvut, int n)
  {
    int i = 0,summa = 0;
    while (i < n) {
      summa += luvut[i];
      i++;
    }
    return summa;
  }

  static void tulosta(int[] luvut, int n)
  {
    for( int i = ( n > luvut.length ? luvut.length : n) - 1; i >= 0; i--)
      System.out.print(luvut[i]+" ");
    System.out.println();
  }

  public static void main(String[] args)
  {
    int luvut[] = new int[TKOKO];
    int n;

    alusta(luvut,TKOKO,3);
    n = montako_mahtuu(luvut,TKOKO,RAJA);
    System.out.println(n+" lukua mahtuuu alle "+RAJA+" näiden summa on "
                       +summaa(luvut,n));
    System.out.print("Luvut ovat: ");
    tulosta(luvut,n);
  }
}

Tehtävä 2.1 Swap-funktio taulukon avulla Toteuta edellisen esimerkin swap-funktio taulukon avulla (laita parametrit taulukkoon). Onko tämä yhtään parempi ratkaisu?
Tehtävä 2.2 Kaksiulotteiset taulukot Muuta Silmu.java-ohjelmaa siten, että se toimii kaksiulotteisilla taulukoilla. Toiminta on muuten sama, mutta tieto varastoidaan kaksiulotteiseen taulukkoon (eli kun yksi taulukon rivi tulee täyteen, aletaan täyttäämään järjestyksessä seuraavaa riviä)

2.3 Olio-ominaisuudet

Seuraavassa esimerkissä toteutetaan luokkahierarkia (käytämme unkarilaista nimeämistapaa, missä c=class ja a=abstract):

Kuva 2.1 Esimerkkiohjelman oliohierarkia

Oliot.java esimerkki perinnästä

abstract class caGraafinenOlio {
  private int x,y;
  private boolean nakyy;

  private boolean paikka(int x, int y){
    this.x = x; this.y = y;
    return false;
  }

  caGraafinenOlio(int x, int y) { paikka(x,y); nakyy = false; }
  caGraafinenOlio() { this(0,0); }
  abstract boolean piirra(); {}
  final boolean nakyvissa() { return nakyy; }

  final boolean sammuta()
  {
    if ( !nakyvissa() ) return true;
    System.out.print("Sammutettu: ");
    nakyy = false;
    return piirra();
  }

  final boolean sytyta()
  {
    if ( nakyvissa() ) return true;
    System.out.print("Sytytetty:  ");
    nakyy = true;
    return piirra();
  }

  boolean siirra(int x, int y) {
    if ( !nakyvissa() ) return paikka(x,y);
    sammuta(); paikka(x,y); return sytyta();
  }

  boolean tulosta(String s) {
    System.out.print(tasaaOik(getClass().getName(),10)+": "
                     +tasaaOik(s,10)+
                     " ("+tasaaVas(""+x,2)+","+tasaaVas(""+y,2)+")" );
    return false;
  }

  public String tasaaOik(String str,int koko) {
    while(str.length() < koko) str += " ";
    return str;
  }

  public String tasaaVas(String str,int koko) {
    while(str.length() < koko) str = " " + str;
    return str;
  }

}
 

abstract class caSateellinenOlio extends caGraafinenOlio {
  private int r;

  private boolean koko(int r) {
    this.r = r; return false;
  }

  caSateellinenOlio(int x, int y, int r) { super(x,y); this.r = r; }
  caSateellinenOlio(int x, int y) { this(x,y,1); }
  caSateellinenOlio() { this(0,0,1); }

  boolean tulosta(String s) {
    super.tulosta(s);
    System.out.print(" r="+r);
    return false;
  }

  boolean muuta_koko(int r) {
    if ( !nakyvissa() ) return koko(r);
    sammuta(); koko(r); return sytyta();
  }
}
 

class cPiste extends caGraafinenOlio {

  cPiste(int x, int y) { super(x,y); }
  cPiste() { this(0,0); }

  boolean piirra() {
    tulosta("Piste"); System.out.println();
    return false;
  }
}
 

class cYmpyra extends caSateellinenOlio {

  cYmpyra(int x, int y, int r) { super(x,y,r); }
  cYmpyra(int x, int y) { this(x,y,1); }
  cYmpyra() { this(0,0,1); }

  boolean piirra() {
    tulosta("Ympyra");  System.out.println();
    return false;
  }
}
 

public class Oliot {

  public static void main(String[] argv)
  {
    caGraafinenOlio p;
    caGraafinenOlio[] kuvat = new caGraafinenOlio[10];

    cPiste p1 = new cPiste(),p2 = new cPiste(10,20);
    cYmpyra y1 = new cYmpyra(1,1,2);
    p1.sytyta(); p2.sytyta();
    p1.siirra(7,8);
    y1.sytyta(); y1.muuta_koko(5);

    p = new cYmpyra(9,9,9);
    p = new cYmpyra(9,9,9);
    p.sytyta(); p.siirra(8,8);
    if ( p instanceof caSateellinenOlio )
      ((caSateellinenOlio) p).muuta_koko(4);
    p.sammuta();

    kuvat[0] = new cYmpyra(10,10,100);
    kuvat[1] = new cPiste(11,11);
    kuvat[2] = new cYmpyra(12,12,102);
    kuvat[3] = null;
    for(int i = 0; kuvat[i] != null; i++ ) kuvat[i].sytyta();
  }

}

Ohjelma tulostaa seuraavaa:
Sytytetty:  cPiste    : Piste      ( 0, 0)
Sytytetty:  cPiste    : Piste      (10,20)
Sammutettu: cPiste    : Piste      ( 0, 0)
Sytytetty:  cPiste    : Piste      ( 7, 8)
Sytytetty:  cYmpyra   : Ympyra     ( 1, 1) r=2
Sammutettu: cYmpyra   : Ympyra     ( 1, 1) r=2
Sytytetty:  cYmpyra   : Ympyra     ( 1, 1) r=5
Sytytetty:  cYmpyra   : Ympyra     ( 9, 9) r=9
Sammutettu: cYmpyra   : Ympyra     ( 9, 9) r=9
Sytytetty:  cYmpyra   : Ympyra     ( 8, 8) r=9
Sammutettu: cYmpyra   : Ympyra     ( 8, 8) r=9
Sytytetty:  cYmpyra   : Ympyra     ( 8, 8) r=4
Sammutettu: cYmpyra   : Ympyra     ( 8, 8) r=4
Sytytetty:  cYmpyra   : Ympyra     (10,10) r=100
Sytytetty:  cPiste    : Piste      (11,11)
Sytytetty:  cYmpyra   : Ympyra     (12,12) r=102

Tehtävä 2.3 Neliö ja suorakaide Lisää esimerkkiin luokka cNelio. Entä cSuorakaide?
Tehtävä 2.4 Väri ja suunta Mieti miten luokkahierarkiaa muutetaan, mikäli kuvioista halutaan värillisiä ja eri asennossa olevia.

2.4 Säikeet ja dynaamiset kontrollit

 
Javassa määritellään säikeet (threads) sisäänrakennettuna ominaisuutena kieleen. Toteutus tosin voidaan hoitaa virtuaalikoneessa käyttöjärjestelmän säikeillä.Seuraava esimerkki luo DecoratedFrame-ikkunassa ( SaieFrame) valmiiksi olevan Käynnistä-näppäimen lisäksi joukon laskureita ( Label). Kun Käynnistä-nappia painetaan, käynnistetään kutakin laskuri-kenttää varten oma prosessi (säie), joka pyörittää kentässä lukuja 0:sta ylöspäin. Kenttää painamalla voidaan ko. säie "tappaa". Ohjelmasta on jätetty listaamatta pääohjelma SaieDemo.java.JBuilder 2.0 pystyy hyödyntämään Java 1.1:ssä olevaa uutta tapahtumankäsittelymallia. Tämä perustuu siihen, että Java 1.1:ssä voi käyttää ns. sisäkkäisiä luokkia. Enää ei tarvitse luoda tapahtumankäsittelijöitä varten irrallisia luokkia, vaan luokat voidaan laittaa pääluokan sisälle. Koska näistä sisäkkäisistä luokista on pääsy pääluokan muuttujia, saadaan säie-esimerkki toimimaan uuden tapahtumankäsittelymallin avulla käyttämällä lisänä muutamaa niksiä.


 
SäieDemo.java - esimerkki säikeistä

import java.awt.*;
import java.awt.event.*;
import borland.jbcl.control.*;
import borland.jbcl.layout.*;

public class SaieFrame extends DecoratedFrame {
  BorderLayout borderLayout = new BorderLayout();
  XYLayout xYLayout2 = new XYLayout();
  BevelPanel bevelPanel = new BevelPanel();
  Button button = new Button();

  final int BUTTON = 1, LABEL = 2;
  final int SAIKEITA = 20;
  final int KIERROKSIA = 1000000;
  int saieNro = 0;
  Label[] label = new Label[SAIKEITA];
  cLaskuri[] laskuri = new cLaskuri[SAIKEITA];
  Object apuObjekti;

  //Construct the frame
  public SaieFrame() {
    try {
      jbInit();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }

  //Component initialization
  public void jbInit() throws Exception{
    int i;

    this.setLayout(borderLayout);
    this.setSize(new Dimension(160, 500));
    this.setTitle("SaieFrame");

    button.setFont(new Font("Dialog", 0, 10));
    button.setLabel("Käynnistä");

    // Sisäkkäinen luokka
    button.addMouseListener(new java.awt.event.MouseAdapter() {
      public void mouseClicked(MouseEvent e) {
        button_mouseClicked(e,button);
      }
    });

    bevelPanel.setLayout(xYLayout2);
    this.add(bevelPanel, BorderLayout.CENTER);
    bevelPanel.add(button, new XYConstraints(70, 21, 71, 26));

    for (i = 0; i < SAIKEITA; i++) {
      label[i] = new Label("0");
      label[i].setFont(new Font("Dialog", 0, 10));
      bevelPanel.add(label[i], new XYConstraints(10, 10 + i*20, 50, 20));
    }
  }

  public void button_mouseClicked(Object o, Object event) {
    for (int i = 0; i < SAIKEITA; i++) {

      if (laskuri[i] != null )
        if ( laskuri[i].isAlive() ) continue;

        laskuri[i] = new cLaskuri(label[i],KIERROKSIA);
        laskuri[i].start();
        laskuri[i].setPriority(laskuri[i].MIN_PRIORITY);

        saieNro = i; // Sisäkkäiseen luokkaan ei voi viedä lokaaleja muuttujia!
      // Sisäkkäinen luokka
        label[i].addMouseListener(new java.awt.event.MouseAdapter() {
          int tamanSaieNro = saieNro; // Säikeen numero myös uuteen luokkaan
          public void mouseClicked(MouseEvent e) {
            label_mouseClicked(e,laskuri[tamanSaieNro]);
          }
        });
    }
   }

  public void label_mouseClicked(Object event,Object o) {
    ((cLaskuri) o).lopeta();
  }

}

class cLaskuri extends Thread {
  Label Text;
  final int PAIVITYS = 5000;
  int n;
  int raja;
  boolean loppuu = false;

  cLaskuri(Label Text, int raja) {
    this.Text = Text;
    this.raja = raja;
    n = 0;
  }

  void lopeta() { loppuu = true; }

  public void run() {
    String mes = "";
    while ( n < raja ) {
      if ( loppuu ) {
        mes = "T"; break;
      }
      count();
    }
    Text.setText("" + n + mes);
  }

  void count() {
    if ( ++n % PAIVITYS == 0 )
      Text.setText("" + n);
  }
}

Tehtävä 2.5 Label => Button Muuta SaieFrame.java-esimerkissä laskurikentät nappuloiksi
.Tehtävä 2.6 Aikaisempien tapahtumankäsittelijöiden käyttö Selvitä helpeistä, kuinka tapahtumankäsittely tapahtui aiemmin. Mieti kuinka säie-esimerkki voitaisiin toteuttaa käyttäen hyväksi tätä vanhempaa menetelmää. Missä vaiheessa tulee ongelmia? 

3. Tietokantojen käyttö

Luvun pääaiheet:  Javan standardeissa luokkakirjastoissa ei ole komponentteja, joiden avulla voidaan kytkeytyä tietokantaan. JBuilderissä voidaan kuitenkin käyttää esim. Borlandin omia beaneja, joilla tietokantaominaisuudet saadaan käyttöön samalla tavalla kuin vastaavissa muissa Borlandin sovelluskehittimissä.

3.1 Tietokantakomponentit


Kuva 3.1 Tietokantakomponenttien toimintaperiaate

Seuraava kuva havainnollistaa tietokantakomponenttien toimintaa JBuilderissa. SQL-palvelin voi periaatteessa olla mikä tahansa ODBC-yhteensopiva tietokanta.

3.2 Yhteyden luominen tietokantaan

3.2.1 InterBasen käyttö tietokantana

Periaatteessa mitä tahansa ODBC-yhteensopivaa SQL-tietokantaa voi käyttää tämän luvun esimerkkien tekemisessä. JBuilder 2.0 :n mukana tulee InterBase 5.0 -nimisen SQL-tietokannan kokeiluversio, joten jos ei muita tietokantoja ole käytettävissä, sitä voidaan käyttää tässä yhteydessä. InterBasen asennus, tietokantojen ja taulujen luominen on kuvattu tarkemmin kirjan liitteessä.

3.2.2 Taulun luominen SQL-tietokantaan

Tauluja voidaan luoda SQL-tietokantaan eri tavoilla. Yksi suoraviivainen, mutta hieman hankala tapa on käyttää SQL-kielen käskyjä taulun luomiseen. Toinen mahdollisuus on luoda taulu tietokannan jollain tarkoitukseen sopivalla työkalulla. Liitteessä on esitetty, kuinka InterBase-pavelimelle voidaan luoda kahdella eri tavalla seuraavissa esimerkeissä käytettettävä taulu.

3.2.3 DSN:n luominen tietokantayhteyttä varten

DSN (Data Source Name) toimii eräänlaisena väylänä, jonka kautta sovellukset voivat käyttää ODBC-tietokantoja. DSN:n avulla voidaan käyttää sekä omassa että muissa koneissa sijaitsevia SQL-tietokantoja. Liitteessä on kuvattu myös DSN:n luominen InterBase-tietokantaa varten. Seuraavassa on DSN:n luomisen pääperiaatteet.Windowsiin DSN:n saa määriteltyä seuraavasti:
  1. Avaa Ohjauspaneeli ( Control Panel )
  2.  Tuplaklikkaa kuvaketta, jossa lukee ODBC (tai ODBC32)
  3.  Avautuvassa ikkunasta paina Add... -nappulaa
 Tietokannan tyyppi valitaan avautuvasta dialogista (esim. InterBase 5.0 tai SQL-Server). Dialogi, jossa kysytään tietokannan tietoja on tietokannan tyypistä riippuen hieman erilainen, mutta seuraavassa on tiedot, joita yleensä tarvitaan.

3.3 Yksinkertaisen tietokantasovelluksen luominen JBuilderillä

Kuva 3.2 "Valmis" puhelinluettelo ilman koodaamista

Aloitamme aivan yksinkertaisella puhelinluettelo esimerkillä. Seuraava ohjelma syntyy kirjoittamatta riviäkään ohjelmakoodia.Kun DSN:n on saatu luotua, voimme tehdä Java-sovelluksen, jolla käsitellään tietokannan taulua.

  1. Luo uusi projekti ensimmäisessä luvussa kuvatulla tavalla. Muista vaihtaa projektin hakemistot oikeiksi projektin ominaisuuksista ( File|Project Properties ).
  2.  Luo uusi sovellus ( File|New|Application)
  3.  Muuta Class-kentän nimeksi vaikka DBSovellus.
  4. Paina Next-näppäintä ja anna sovelluksen pääikkunalle nimeksi esimerkiksi Puhelinluettelo.
  5. Aluksi tarvitaan komponentti, joka luo yhteyden SQL-tietokantaan. Valitse DataExpress-sivu ja sijoita sieltä Database-komponentti () lomakkeelle. Anna komponentille nimeksi databasePuh. Komponentti ei tule näkyviin lomakkeelle, vaan se näkyy vasemmalla olevassa komponettihierarkiassa Data Access -haarassa.
  6. Seuraavaksi tietokantakomponentti pitää kytkeä DSN:n kautta SQL-palvelimeen. Klikkaa databasePuh-komponentin connection-ominaisuudessa olevaa valitsinta (). Avautuvasta dialogista valitse Choose URL . Paina Show Data Sources -nappia ja aiemmin luodun DSN:n näkyy koodattuna seuraavasti: jdbc:odbc:Omakanta <sun.jdbc.odbc.JdbcOdbcDriver> Paina Ok.
  7. Nyt tarvitaan käyttäjätunnus ja salasana tietokantaan. InterBasen ylläpitäjän nimi on sysdba ja salasana oletuksena masterkey. Syötä tämä tai mahdollinen muu tunnus dialogiin. Voit testata, toimiiko yhteys painamalla Test Connection -nappia. Paina lopuksi Ok.
  8. Seuraavaksi tarvitsemme komponentin, joka suorittaa haun tietokannassa ja varastoi sen tulokset. Lisää tätä varten QueryDataSet-komponentti () lomakkeelle. Näet taas uuden komponentin ilmestyvän komponenttihierarkiaan vasemalle. Nimeä komponentti queryDataSetPuh:ksi
  9. Paina komponentin ominaisuuden query valitsinta. Avautuvasta dialogista valitse Database-kohdassa edellä luotu tietokanta ( databasePuh). Poista rasti Place SQL text in resource -ruudusta.
  10. Voit katsella tietokannan tauluja Browse tables -napilla. Kirjoita SQL-statement-ruutuun: select * from puh . Voit testata juuri kirjoittamasi hakuoperaation toimivuuden Test query -napilla. Paina vielä Ok.
  11. Nyt tarvitsemme enää komponentteja, jotka osaavat näyttää haun tulokset. Parhaan yleisnäkymän tietokantaan saa GridControl-komponentilla (), joka löytyy JBCL-välilehdeltä. Sijoita taulu lomakkeelle ja vaihda sen dataSet-ominaisuudeksi edellisessä kohdassa luotu queryDataSetPuh ja nimeksi gridControlPuh.

  12. Lisätään vielä komponentti, jolla on helppo liikkua taulukossa edestakaisin, NavigatorControl (). Muuta seuraavat ominaisuudet:
    name = navigatorControlPuh
    dataSet = queryDataSetPuh
  13. Lopuksi komponentti, joka näyttää isolla taulun aktiivisen rivin kohdalla olevan henkilön nimen, LabelControl (). Ominaisuudet:
  14. name = labelControlNimi
    background = Yellow
    dataSet = queryDataSetPuh
    columnName = NIMI
    font = "SansSerif", Bold, 18

3.4 Layoutien käyttö Javassa

Javassa komponenttien sijoittelussa on luotu menetelmä, jonka avulla saadaan säilytettyä ulkonäkö, vaikka siirrytään käyttöjärjestelmästä toiseen. Tähän tarkoitukseen käytetään alustoihin liittyviä layout-komponentteja. Nämä layoutit määrittelevät kuinka komponentit sijoittuvat loogisesti esim. paneelille. Käytettävä systeemi määrää todelliset paikat, kun ohjelmaa ajetaan.Layoutja on erilaisia ja seuraavassa esitellään niistä tärkeimpiä. Erilaisten layoutien käyttö vaatii hieman totuttelua ja sitä kannattaakin harjoitella kokeilemalla kuinka eri layotit sijoittelevat samat komponentit alustalle.

3.4.1 XYLayout

XYLayout on Borlandin oma layout, joka sijoittaa komponentit alustalle tarkasti koordinaattien mukaan. Tämä layout on tarkoitettu vain suunnittelukäyttöön, koska koordinaattijärjestelmät vaihtelevat systeemien välillä

Kuva 3.3 XYLayout
.

3.4.2 BorderLayout

BorderLayout jakaa alustan viiteen osaan. Kullekin komponentille voidaan määritellä, mihin näistä osista se sijoitetaan. Tämän layoutin kanssa voi käyttää järkevästi vain viittä komponenttia, koska loput komponentit joutuvat toisten komponenttien alle. Tosin, jos yksi komponentti on esim. paneeli, voidaan sen päälle taas liittää uusia komponentteja, jolloin saadaan mutkikkaampia kokonaisuuksia.

Kuva 3.4 BorderLayout

3.4.3 FlowLayout

FlowLayout laittaa komponentit yksinkertaisesti peräkkäin alustalle. Komponenttien kokoon ei voi vaikuttaa, mutta niiden järjestystä voi vaihdella.

Kuva 3.5 FlowLayout

3.4.4 GridLayout

GridLayout jakaa paneelin ruudukkoon, johon komponentit sijoitetaan. Ruudukon kokoon voi vaikuttaa jossain määrin layoutin ominaisuuksia muuttamalla.

Kuva 3.6 GridLayout

3.4.5 GridBagLayout

GridBagLayout on monipuolisin ja samalla hankalin Javan standardikirjastoon sisältyvä layout. Seuraavassa on esitelty esimerkin avulla sen muutamia perusominaisuuksia.
  1. Tee uusi kehys valitsemalla valikosta File|New Frame
  2. Valitse D esign-välilehti ja muuta kehyksen layout-ominaisuudeksi GridBagLayout.
  3.  Lisää kehykseen FieldControl, TextControl ja kolme ButtonControlia valitsemalla kukin komponentti työkalupaneelista ja napsauttamalla ne lomakkeelle.
  4. Huomaat, kuinka komponentit sijoittuvat eräänlaisen ruudukon sisälle. Voit siirrellä komponentteja tarttumalla niihin ja päästämällä irti oikean "lokeron" kohdalla. Siirtele komponentit seuraavan kuvan mukaisille paikoille ja muuta nappuloiden ja tekstikentän nimet sopiviksi. Voit vielä muotoilla TextControl-kenttiä siten, että sen reunat näkyvät ja teksti on keskellä kehystä (ominaisuudet: alignment ja drawEdge). Kehyksen pitäisi näyttää nyt suunnilleen seuraavalta:

  5. Kuva 3.7 GridBagLayout-ruudukko
  6. Kussakin lokerossa olevan komponentin käyttäytymistä suhteessa muihin komponentteihin ja koko ruudukkoon voidaan määritellä Contraints-dialogin avulla. Komponenttiin liittyvän dialogin saa auki aktivoimalla komponetin ja valitsemalla oikean hiiren napin painalluksella aukeavasta valikosta Constraints...

  7. Kuva 3.8 Constraints-dialogi
  8. Valitse tekstikenttä aktiiviseksi ja avaa Constraints-dialogi. Levitetään tekstikenttä täyttämään kaksi lokeroa vaakatasossa ruudukossa. Tämä tapahtuu muuttamalla kenttää Width arvo 2. Paina Ok ja seuraa, mitä tapahtuu.
  9. Jos lomakkeen kokoa muutetaan, voisi olla hyvä, jos saataisiin jotkin komponenteista seuraamaan koon muutosta, siten että tyhjä tila peittyy. Saamme tekstikentän käyttäytymään tällä tavoin, kun anamme sille "painoa", jonka mukaan se täyttää aluetta kehyksessä. Avaa Constraints-dialogi uudelleen ja muuta kentät Weight x/y arvoon 3. Paina Ok ja muuttele kehyksen kokoa.
  10. Nappulatkin saadaan käyttäytymään vastaavasti muuttamalla niiden x/y-painoiksi 1 vastaavalla tavalla kuin tekstikehyksellekin. Muuttele taas kehyksen kokoa ja huomaat, että tekstikentän ja nappuloiden tilanvaraus pystysuunnassa jakaantuu suhteessa 1:3, kuten painoiksi asetettiin.
  11. Komponentit voidaan myös määrätä täyttämää koko lokero, jossa ne sijaitsevat. Valitse FieldConrol-kentän Constraints-dialogi ja vaihda alareunassa oleva Fill radio -button asentoon Horizontal. Kenttä levenee koko lokeron levyiseksi. Tämä operaatio ei kuitenkaan antanut kentälle omaa painoarvoa, vaan vain se leveys käytetään, mikä muilta jää yli.
  12. Jos huomasit aiemmassa vaiheessa, että jokin nappula täyttää koko ruudun, edellisessä kohdassa oleva täyttöominaisuus on mahdollisesti mennyt automaattisesti päälle. Saat korjattua tilanteen, kun valitset Constraints-dialogista Fill-kohdan arvoon None.

Kuva 3.9 GridBagLayoutin käyttö

3.4.6 Puhelinluettelo GridBagLayoutia käyttäen

Muutetaan seuraavaksi puhelinluetteloesimerkiämme siten, että se käyttää komponenttien sijoittelussa GridBagLayoutia.
  1. Vaihda lomakeella olevan bevelPanelinlayout-ominaisuudeksi GridBagLayout. Edellisen layoutin mukaiset asetukset pyritään säilyttämään mahdollisimman tarkasti, mutta joitain kompromisseja joudutaan tekemään.
  2. Halutessasi voit hienosäätää komponenttien sijoittumista lomakkeelle. Huomaa, että Constraints-dialogissa External Insets -osio määrittelee, kuinka paljon komponentin ympärille jätetään tyhjää tilaa lokeron sisällä.

3.5 SQL-kyselyt


Kuva 3.10 SQL-hakuehto

SQL-komponenttiin laitettiin hakuehto select * from puh Tämä tarkoittaa, että valitaan kaikki kentät ( *) taulusta puh. Muutetaan ohjelmaa siten, että hakuehto voidaan kirjoittaa itse.

  1. Lisää komponentit FieldControl ja ButtonControl napsauttamalla ne lomakkeen oikeaan yläkulmaan. Tietokone luo automaattisesti lisää ruutuja layoutiin ja voit halutessasi muuttaa komponenteihin liittyviä Constrainsts-ominaisuuksia (esimerkiksi tekstikentällä on enemmän painoarvoa kuin nappulalla).
  2.  FieldControl:
       name = fieldControlHakuehto 
       text = 'select * from puh'
     ButtonControl:
       name = buttonControlHae
       label = 'Hae'
  3. Laita Hae-nappulan tapahtumaksi:
  4.  try {
       queryDataSetPuh.close();
       queryDataSetPuh.setQuery(
         new borland.sql.dataset.QueryDescriptor(databasePuh,
         fieldControlHaku.getText(), null, true, Load.ALL));
       queryDataSetPuh.executeQuery();
     } catch (Exception excep) {
       ExceptionDialog exDialog = new ExceptionDialog(this,"SQL-virhe!", excep);
       exDialog.show();
     }
  5. Kokeile ajaa ohjelmaa esim. SQL-hakuehdoilla:
  6.  1: select nimi from puh
     2: select nimi,postinumero from puh
     3: select * from puh where nimi > "Bond"
     4: select * from puh where nimi like "%p%"
     5: select * from puh where Upper(nimi) like "%P%"
     6: select nimi,osoite from puh order by osoite
     7: select osoite from puh
Voisimme vielä muuttaa ohjelmaa siten, että "isossa" kenttäikkunassa näkyy aina aktiivisen kentän arvo:
  1. Lisää käsittelijä taulukon sarakkeen vaihtumiselle ( Events-sivu, subfocusChanged-tapahtuma)
  2. void gridControlPuh_subfocusChanged(MatrixSubfocusEvent e) {
      labelControlNimi.setText(gridControl1.getModel().
                               get(e.getLocation().row,e.getLocation().column).
                               toString());
    }

3.6 Dynaamisesti luotavat data-komponentit

Tähän asti olemme käyttäneet puhelinluettelon tietojen esittämiseen vain taulukkoa. Tietoja voitaisiin myös esittää lomakemuodossa, jossa tieto on esitetty kentissä. Valitettavasti JBuilder 2.0 ei sisällä erillistä Wizardia, joka osaisi helposti generoida tietokanta-dialogeja, vaan kentät joudutaan rakentamaan itse. Voisi lisäksi olla hyvä, jos kentät voitaisiin muodostaa dynaamisesti esim. hakutulosten perusteella.Muutetaan vielä ohjelmamme sellaiseksi, että siinä on kaksi sivua:
  1. sivu, jolla näkyy taulu taulumuotoisena
  2. sivu, jolla aktiivinen tietue näkyy lomakemuotoisena, lomake generoidaan haun perusteella dynaamisesti

3.6.1 TabsetPanel

Lisätään aluksi gridControlPuh:in tilalle "lärpsykkäkirja":
  1. Aktivoi gridControlPuh ja leikkaa se leikekirjaan ( Ctrl-C).
  2.  Klikkaa dialogin alareunaan TabsetPanel ( JBCL Containers -sivu)
  3.  name  = tabsetPanelPuh
     Constraints:
     Width = 3
     Wight/Y = 1
     Fill = Both
  1. Aktivoi tabsetPanelPuh ja liitä leikekirjan sisältö. JBuilder luo automaattisesti uuden sivun.
  2. Uuden sivun nimeksi tuli komponentin nimi. Saat sen vaihdettua muuttamalla sivulle tulleen taulukko-komponentin Constraints-ominaisuutta esim. arvoon Taulu.
  3. Nimen muutos päivittyy suunnittelutilaan vasta, kun JBuilder rakentaa näkymän uudelleen. Saat tämän aikaan tekemällä jonkun pienen muutoksen, esimerkiksi välilyönnin lisäämisen Source-tilassa ja palaamalla takaisin Design-tilaan.

  4. TabsetPanelissa voit vaihtaa aktiivista sivua joko valitsemalla komponenttihierarkiasta halutulla sivulla olevan komponentin tai muuttamalla paneelin selectedIndex-ominaisuutta osoittamaan halutulle sivulle. Valitse aktiiviseksi sivu 0.Aktivoi tabsetPanelPuh ja lisää tälle sivulle bevelPanel (JBCL Containers ) JBuilder luo jälleen automaattisesti uuden sivun.
     name = bevelPanelLomake
     constraints = Lomake
     bevelInner = Flat
     layout = GridBagLayout
  5. Kokeile ajaa ohjelmaa.

3.6.2 Data-kontrollien lisääminen dynaamisesti

Dynaamisten kenttien käyttö Javassa on varsin huoletonta. Javassa ei tarvitse itse huolehtia olioiden tuhoamisesta, vaan automaattinen roskien keruu poistaa oliot, kun niihin ei ole enää viittauksia. Tässä esimerkissä vanhojen kenttien poistamiseksi riittää pelkästään niiden poistaminen paneelista. Tämän lisäksi voidaan käyttää tehokkaasti avuksi GridBagLayoutia, joka osaa sijoitella dynaamisesti luotavat komponentit annettujen pääohjeiden perusteella paneelille. Näin ollen dynaamisten komponenttien käyttöön riittää vain yksi aliohjelma.Lisää ohjelmaan seuraava aliohjelma ja lisää toimintaa Päivitä-napille. Kokeile tämän jälkeen ajaa ohjelmaa.
 
void luoKentat() {
    int i;
    boolean onko_valittu;
    FieldControl apuFieldControl;
    BevelPanel bevelPanelTayte = new BevelPanel();
    bevelPanelTayte.setBevelInner(BevelPanel.FLAT);

    bevelPanelLomake.removeAll(); // Edellisen kerran elementit pois

    // Otetaan talteen kenttien nimet, jotka esiintyvät haun tuloksessa
    String[] nimet = 
             queryDataSetPuh.getColumnNames(queryDataSetPuh.getColumnCount());

    for (i=0; i < queryDataSetPuh.getColumnCount(); i++) {
      // Joskus systeemi ottaa hakuun mukaan kenttiä, joita ei haluta näyttää
      try { if (!queryDataSetPuh.columnIsVisible(nimet[i])) continue; }
      catch (Exception excep) {}

      // Luodaan teksti-kenttä, jossa on tietokannan kentän nimi
      bevelPanelLomake.add(new TextControl(nimet[i]) ,
        new GridBagConstraints2(0, i, 1, 1, 1.0, 0.0,GridBagConstraints.CENTER,
        GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));

      // Luodaan edit-kenttä, jossa on tietokannan kentän arvo
      apuFieldControl = new FieldControl();
      apuFieldControl.setDataSet(queryDataSetPuh);
      apuFieldControl.setColumnName(nimet[i]);
      bevelPanelLomake.add(apuFieldControl,
        new GridBagConstraints2(1, i, 1, 1, 4.0, 0.0,GridBagConstraints.CENTER,
        GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
    }
 
 

    // Lisätään paneeli, joka "puristaa" edellä luodut elementit ylälaitaa vasten
    bevelPanelLomake.add(bevelPanelTayte,
        new GridBagConstraints2(1, i+1, 1, 1, 0.0, 1.0,GridBagConstraints.CENTER,
        GridBagConstraints.VERTICAL, new Insets(0, 0, 0, 0), 0, 0));
  }

void buttonControlHae_actionPerformed(ActionEvent e) {
    try {
      queryDataSetPuh.close();
      queryDataSetPuh.setQuery(
  new borland.sql.dataset.QueryDescriptor(databasePuh,
           fieldControlHaku.getText(), null, true, Load.ALL));
      queryDataSetPuh.executeQuery();
      luoKentat();
    } catch (Exception excep) {
      ExceptionDialog exDialog = new ExceptionDialog(this,"SQL-virhe!", excep);
      exDialog.show();
    }
}


Kuva 3.11 Valmis Java-kielinen puhelinluettelo

4. Omien JavaBeanien tekeminen

Luvun pääaiheet:

4.1 Miksi omia JavaBeaneja?

Java sisältää varsin hyvän tuen omien komponenttien tekemiselle. Se määrittelee jopa ominaisuuksia, joita käytetään ohjelmissa, jotka tuottavat beaneja. Yleispätevät JavaBeanit ovat käyttöjärjestelmäriippumattomuutensa takia varsin hyödyllisiä ohjelmoinnin apuvälineitä.JBuilder 2.0:ssa omien beanien tekeminen on varsin vaivatonta. Koska Javassa bean-ajattelu on niin vahvana mukana koko ajan, lähes kaikista Java-luokista voidaan tehdä bean. Usein suunnittelua ei tarvitse muuttaa suurestikaan, jos huomaa, että haluaa tehdä joistain komponenteistaa beanin.Hyvin tehtyjen ja testattujen komponenttien avulla ohjelmointi on helppoa ja koodin kirjoittamisen tarve vähenee radikaalisti. Oikeastaan aina kun tekee uuden luokan, kannattaa miettiä olisiko siitä uudelleen käytettäväksi komponentiksi.

4.2 Laskurina toimivan beanin luominen

Seuraavaksi teemme Javalla komponentin, johon on sisällytetty laskurin osat: lisäysnappula ja lukumääräruutu. Tämän lisäksi komponettiin lisätään käyttöön liittyviä toimintoja. Tätä komponenttia voidaan käyttää sitten hyväksi vaikka autolaskurin luomisessa. 

4.2.1 Beanin luominen JavaBean-Wizardia

  1. Sulje mahdollisesti auki olevat projektit.
  2. Valitse File-valikosta New-kohta.
  3.  Avautuneesta dialogista tuplaklikkaa JavaBean-Wizardia
  4.  Täytä avautuneeseen ProjectWizard-dialogiin projektin ja projektitieodoston nimi ja paina Finish-nappulaa.
  5.  Seuraavaksi aukeavan dialogin package-kohtaan teksti Beanit. Tämä tekee beanin tiedoston tämän nimiseen alihakemistoon. Kohtaan Name of New Bean kirjoita LaskuriBean. Paina lopuksi Ok. JBuilder luo lähdekoodin beanille.
  6. Lisätään tarvittavat ominaisuudet beaniin. Valitse suunnitteluikkunaan Bean-sivu painamalla alareunassa olevaa Bean-välilehteä. Valitse ylemmistä välilehdistä Properties.

4.2.2 Ominaisuuksien lisääminen

  1. Paina Add Property -nappulaa ja saat esiin dialogin, jossa määritellään ominaisuuksia. Kirjoita teksti laskettavatProperty Name -kohtaan. Haluttu ominaisuuden tyyppi String on oletuksena. Paina lopuksi Ok.
  2.  Lisätään vielä ominaisuus, jossa säilytetään laskettujen autojen määrää. Paina jälleen Add Property ja anna nimeksi maara, ja tyyppi-kenttään kirjoita int. Paina vielä Ok.
  3.  JBuilder on lisännyt kummallekin ominaisuudelle sekä get- että set-metodit
  4.   public void setLaskettavat(String newLaskettavat) {
        laskettavat = newLaskettavat;
      }

      public String getLaskettavat() {
        return laskettavat;
      }

      public void setMaara(int newMaara) {
        maara = newMaara;
      }

      public int getMaara() {
        return maara;
      }

4.2.3 Osien lisääminen Beaniin

  1. Valitse suunnitteluikkunaan Design-välilehti. Vaihdetaan BeanPanelinlayout-ominaisuus FlowLayoutiksi. Tämän layoutin avulla saadaan automatisoitua komponenttien sijoittelu paneelille.
  2. Lisää ButtonControl,() paneelille. Anna nimeksi lisaaButton ja label-ominaisuudeksi Lisää, tämä teksti tulee olemaan nappulan oletusteksti.
  3. Lisää vielä FieldControl,() ja muuta sen nimeksi vaikkapa laskuriField ja ominaisuus EditInPlacefalse:ksi. Aseta tekstiksi 0 ja alignmentiksi Right+Middle.
  4. Muuttele paneelin kokoa ja huomaat kuinka komponentit liikkuvat paneelilla valitun layoutin mukaan. Aseta koko lopulta sellaiseksi, että lopputulos näyttää seuraavalta: 



Kuva 4.1 LaskuriBean

4.2.4 Toimintojen lisääminen Beaniin

  1. Tuplaklikkaa Lisää-nappulaa, ja lisää seuraava koodi toiminnan kohdalle
  2. void lisaaButton_actionPerformed(ActionEvent e) {
        maara = maara + 1;
        laskuriField.setText(""+maara);
      }
  3. Lisätään beanin laskettavat-ominaisuuden set-metodiin rivi, jolla saadaan nappulan nimi päivittymään näytölle aina kun sitä muutetaan.
  4. public void setLaskettavat(String newLaskettavat) {
      lisaaButton.setLabel(laskettavat);
      laskettavat = newLaskettavat;
    }
  5. Hyödyllinen ominaisuus beanilla voisi olla metodi, jota kutsumalla laskuri nollautuu. Lisätään vielä sellainen.
  6. public void Nollaa() {
        maara = 0;
        laskuriField.setText("0");
    }

4.3 LaskuriBeanin käyttö 

4.3.1 Beanin kääntäminen ja muutosten tekeminen

Jotta beania voitaisiin käyttää, se täytyy kääntää. Tämä tapahtuu Build-valikosta käskyllä Make "LaskuriBean.java" . Tämän jälkeen bean on käytettävissä seuraavassa kohdassa.Jos beania halutaan muokata, pitää se vain muokkauksen jälkeen kääntää uudelleen ja JBuilder hoitaa tarvittavat päivitykset muualla. Uudelleenkääntäminen tapahtuu valitsemalla Build|Rebuild "LaskuriBean.java" . Huomaa, että pelkkä uudelleenkääntäminen ei auta, jos olet paketoinut beanin jäljempänä selitettävällä tavalla. Silloin bean täytyy asentaa uudelleen työkaluvalikkoon.

4.3.2 Beanin lisääminen komponenttipalettiin

Jotta voisimme käyttää beaneja, ne täytyy lisätä työkaluvalikkoon. Tämä toiminta on kuvattu kohdassa 1.3.1. Kun haluamme koekäyttää kehittelyvaiheessa olevaa beania, järkevintä on käyttää välilehteä Add from Package . Tällöin käytetään hakemistorakenteessa olevia käännettyjä Java-luokkia.
  1. Avaa lisäys-dialogi kuten kohdassa 1.3.1.
  2. Valitse Browse-näppäimellä hakemisto, jossa edellisen kohdatn kääntämisestä tullut LaskuriBean.class-tiedosto sijaitsee (löytyy File|Project Propeties -dialogin output root directory n osoittamasta paikasta). Paina Ok.
  3.  Valitse listasta LaskuriBean ja paina Install. Paina lopuksi Ok.
  4.  Nyt äsken tehty bean on valmiina koekäytettäväksi.

4.3.3 Autolaskurin tekeminen beanien avulla

Kokeillaan kuinka autolaskurin tekeminen onnistuu beanien avulla.
  1. Luo uusi sovellus (tai vaikka koko projekti) edellisiä esimerkkejä noudattaen. Anna sovellukselle nimeksi vaikka BeanAutolaskuri.
  2.  Lisää paneelille kaksi laskuriBeania työkaluvalikosta. Nimeä ne sopivasti ja muuta laskettavat-ominaisuuksiin Kuorma-autoja ja Henkilöautoja.
  3.  Lisää nappula nollausta varten. Toimintakoodiin kirjoita:
  4. void nollaaButton_actionPerformed(ActionEvent e) {
        laskuriBean1.Nollaa();
        laskuriBean2.Nollaa();
    }
  5. Aja ohjelma.
     

Kuva 4.2 Autolaskuri beanien avulla tehtynä

4.4 Beanin paketoiminen siirrettävään muotoon

Kun bean ja siihen liittyvät muut Java-luokat halutaan pakata kätevästi siirrettävään muotoon, käytetään vastaavaa menetelmää, jolla kohdassa 1.7.2 pakattiin koko sovellus yhdeksi jar-paketiksi.
  1. Valitse Wizards|Deployment Wizard .
  2.  Avautuvassa dialogissa valitse vasemmalla olevasta listasta vain LaskuriBean.java.
  3.  Rastita Include JBCL ja Include JGL , niin Borlandin omat Java-luokat tulevat pakeissa mukana, eikä niiden tarvitse olla installoituna järjestelmässä, jossa beania halutaan käyttää.
  4. Kirjoita dialogiin sopiva polku ja tiedostonimi. Paina lopuksi Ok.
  5.  Tämän jälkeen bean on kätevästi yhdessa tiedostossa, jota voidaan käyttää täsmälleen kuten kohdassa 1.3.1 on kuvattu. Huomaa, että voit pakata samaan jar-pakettiin useitakin beaneja.
Tehtävä 4.7 Monta autoa kerralla Lisää LaskuriBeaniin toinen nappula, joka lisää kerralla erillisenä ominaisuutena määritettävän määrän autoja. Nappulassa tulee myös näkyä, montako autoa lisätään.
Tehtävä 4.8 AutolaskuriBean Tässä hieman haastavampi tehtävä. Tee bean, joka on itsessään autolaskuri! Ominaisuutena mm. merkkijono, jossa on pilkuilla eroteltuna laskettavien autojen nimet. Vihjeitä:
  1. Käytä apuna StringTokenizer-luokkaa.
  2. Katso tietokantoja käsittelevästä luvusta, kuinka saadaan dynaamisesti luotua komponentteja.
  3. Käytä hyväksi sopivaa layoutia, joka sijoittelee laskuri-komponentit paneelille.

5. Liite: InterBase-tietokannan asennus

Luvun pääaiheet:

5.1 SQL-tietokantajärjestelmä

Nykypäivänä useimmat SQL-tietokannat tukevat ODBC (Open DataBase Connectivity)- rajapintaa, jonka kautta tietokantaa voidaan käyttää. Javassa tietokantoja varten on oma tietokantarajapinta JDBC (Java DataBase Connectivity). Tämä rajapinta ei voi suoraan käyttää ODBC-rajapintaa, vaan välissä täytyy olla silta, joka muuttaa JDBC:lle tulevat pyynnöt ODBC-rajapinnalle kelpaaviksi.
Kuva 5.1 SQL-tietokannan käyttö JAVA:ssa

Tietokantaa käyttävään tietokoneeseen pitää määritellä portti, jonka kautta päästään käyttämään tietokantapalvelimella olevaa tietokantaa. Tätä porttia kutsutaan nimellä DSN (Data Source Name). DSN:ssä määritellään tietokannan käyttöön tarvittavat parametrit, kuten tietokantapalvelimen osoite, käytettävä tietokanta ja käyttäjätunnus ja salasana. Sovellus osaa kutsua tämän DSN:n kautta varsinaista tietokantaa.

5.2 InterBase 5.0 - asennus

  1. Käynnistä Interbase:n asennusohjelma.
  2. Mene asennusohjelman ruutuja eteenpäin kunnes tulet lisenssiruutuun. Saat käyttöösi 90 päivän kokeilulisenssin kirjoittamalla molempiin kenttiin eval.
  3.  Valitse haluamasi asennusoptiot. Välttämättömiä ovat ainakin InterBase Server , InterBase Client , InterBase Windows Tools ja InterBase ODBC Driver .
  4.  Seuraavaksi valitaan, käynnistetyykö InterBase automaattisesti Windowsin käynnistyksen yhteydessä, vai suoritetaanko käynnistys manuaalisesti. Kannattaa ehkä valita manuaalinen käynnistys jos tietokantaa käytetään melko harvoin.
  5. Seuraavassa ruudussa InterBase Guardiania koskevassa kysymyksessä valitse Automatic Restart . Varsinainen asennus alkaa tämän jälkeen.
  6. Kun asennus on valmis, kysytään halutaanko InterBase Guardian käynnistää. Voit vastata myöntävästi.
  7. InterBase on nyt käyttöä varten valmiina. Jos tietokantapalvelin ei jostain syystä käynnistynyt, sen saa käynnistettyä valitsemalla WindowsinStart-valikosta Programs|InterBase 5.0|InterBase Server .

5.3 SQL-tietokannan luominen InterBase-tietokantaan

5.3.1 Tietokannan luominen

Kun InterBase-palvelin on asennettu, pitää luoda sinne tietokanta.


Kuva 5.2 Tietokannan luominen InterBase-palvelimelle

  1. Käynnistä InterBase Interactive SQL -työkalu (löytyy käynnistysvalikosta Programs|InterBase 5.0 )
  2.  Valitse valikosta File|Create Database ja seuraava dialogi aukeaa
  3. Kirjoita kohtaan Database jokin .gdb -päätteinen tiedostonimi täydellisen polun kanssa, esimerkiksi D:\omat\majole\omakanta.gdb.
  4.  Syötä käyttäjän tunnistustiedot: Username:SYSDBAPassword:masterkey. Tämä on InterBasen-palvelimen ylläpitäjän tunnus, joka luodaan automaattisesti asennuksen yhteydessä. Ylläpitäjällä on automaattisesti täydet oikeudet tietokantojen käyttöön.
  5. Paina OK.

5.3.2 Taulun luominen SQL-lauseella

  1. Seuraavaksi luodaan taulu tietokantaan. relaatiotietokannassa tiedot tallettetaan tauluihin, jotka sisältävät erityyppisiä kenttiä. Yhdessä tietokannassa voi olla useampiakin tauluja.
  2. Nopeimmin taulun luominen käy käyttäen InterBasen omaa SQL-murretta. InterBasessa on kuitenkin se huono puoli, ettei se sisällä hyvää työkalua, jolla voitaisiin syöttää tietoja suoraan juuri luotuun tauluun.
  3. CREATE TABLE PUH
    (
      Nimi VARCHAR(30) NOT NULL PRIMARY KEY, 
      Puh VARCHAR(20),
      Puh2 VARCHAR(20),
      Puh3 VARCHAR(20),
      Fax VARCHAR(20),
      Osoite VARCHAR(30),
      Postinumero VARCHAR(5),
      Postiosoite VARCHAR(25),
      Lisatietoja VARCHAR(50) 
    );

5.3.3 Taulun luominen DataBase Desktopilla

Taulu voidaan myös luoda käyttäen esim. Borlandin omaa DataBase Desktop -työkalua, joka tulee esim. Delphin mukana. Tätä tapaa varten joudutaan kuitenkin tekemään aluksi hieman enemmän työtä.
  1. Käynnistä DataBase Desktop .
  2.  Ensin luodaan alias, joka osoittaa äsken luotuun tietokantaan. Tämä onnistuu valitsemalla DBD:stä Tools|Alias manager . Paina New-nappulaa ja dialogi näyttää suunnilleen seuraavalta (jos dialogissa on vain muutama rivi, kokeile valita Driver type -arvoon INTRBASE, vaikka se olisikin jo valittuna):


  3. Kuva 5.3 Taulun luominen InterBase-tietokantaan
  4. Keksi joku nimi aliakselle, esimerkiksi OMA_IB. Kirjoita se Database alias -kohtaan.
  5. SERVER NAME -kohtaan kirjoita tietokannan tiedostonimi koko polun kanssa.
  6. USER NAME -kohtaan tulee käyttäjätunnus, eli SYSDBA tässä tapauksessa.
  7. Painamalla Keep New -nappulaa, saadaan uusi alias säilymään auki olevan istunnon ajan, mutta se joudutaan luomaan uudestaan joka kerta, kun tietokantaa halutaan muuttaa.
  8. Alias saadaan tallettua pysyvästi painamalla Save As -nappulaa. Ohjelma kysyy talletettavan konfiguraatiotiedoston nimeä, vastaa varmistukseen myönteisesti.
  9. Nyt voidaan luoda uusi taulu tietokantaan. Valitse siis File|New|Table ja avautuvasta valintalistasta tyypiksi INTRBASE.

  10. Kuva 5.4 Taulun luominen Database Desktopin avulla
  11. Kirjoittele avautuneeseen tauluun tarvittavat kentät.
  12. Paina Save As -nappulaa ja valitse dialogin alareunasta kohdasta Alias juuri äsken luotu alias. Syötä salasana avautuvaan dialogiin.
  13. Tämän jälkeen voit mukavasti kirjoitella tietoja tauluun, kunhan ensin avaat sen käskyllä File|Open|Table. Valitse dialogin alareunasta alias OMA_IB. Tämän jälkeen saat näkyviin juuri luodun taulun. Saat sen käyttöön tuplaklikkaamalla sitä.

5.4 DSN:n luominen InterBasen käyttöä varten

Jotta edellä luotu tietokanta saataisiin käyttöön, on luotava DSN, jonka toimii väylänä tietokantapalvelimelle.
  1. Avaa Ohjauspaneeli ( Control Panel )
  2.  Tuplaklikkaa kuvaketta, jossa lukee ODBC (tai ODBC32)
  3.  Valitse avautuvassa ikkunasta System DSN -välilehti ja paina Add... -nappulaa
  4. Tuplaklikkaa InterBase 5.x Driver -riviä ja seuraava dialogi aukeaa:

  5. Kuva 5.5 InterBase 5.0 DSN:n luominen
  6. Laita Data Source Name -kohtaan vaikka Omakanta.
  7. Database-kohtaan kirjoita äsken luomasi tietokannan tiedostonimi täydellisen polun kanssa
  8. Laita vielä käyttäjän tunnistustiedot edelliseen tapaan: Username:SYSDBAPassword:masterkey.
  9. Paina lopuksi OK. Nyt tietokanta on valmis käytettäväksi vaikkapa Java-ohjelmasta.

  10.  

Kirjallisuutta:

Arnold Ken, Gosling James, "The Java Programming Language" , Addison-Wesley, 1996
David Flanagan, "Java - tehokäyttäjän opas" , Suomen ATK-kustannus, 1997
Lappalainen Vesa, "Delphi pikakurssi" , Jyväskylän yliopisto,Matematiikan laitos, 1996

Linkkejä:

Borland,"JBuilder Developer Support" , http://www.borland.com/devsupport/jbuilder/
JavaSoft, "JDK 1.1.8 Documentation" , http://java.sun.com/products/jdk/1.1/docs/index.html
Campione Mary, Walrath Kathy, "Java tutorial" , http://java.sun.com/docs/books/tutorial