LuK-tutkielma 28.5.1999
Markku Lehtinen
Jyväskylän yliopisto, tietotekniikan laitos
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.
void buttonControlHA_actionPerformed(ActionEvent e) { } |
labelControlHA.setText(""+(Integer.parseInt(labelControlHA.getText())+1)); |
labelControlHA.setText("0");labelControlKA.setText("0"); |
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>
|
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 {
//Construct the application public Autolaskuri() {
public static void main(String[] args) {
|
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
public LaskuriFrame() {
//Component initialization private void jbInit() throws Exception {
void buttonControlHA_actionPerformed(ActionEvent e) {
void buttonControlKA_actionPerformed(ActionEvent e) {
} |
Tehtävä 1.1 Polkupyörät Lisää ohjelmaan myös polkupyörien laskeminen.
void timerBeanHA_timerAction(TimerEvent e) {
imageBeanHA.setLocation(imageBeanHA.getLocation().x + 1, imageBeanHA.getLocation().y); } |
File Options Help
Exit Colors About |
void menuItemExit_actionPerformed(ActionEvent e) {
System.exit(0); } |
void menuItemColors_actionPerformed(ActionEvent e) {
colorChooserTausta.show(); if (colorChooserTausta.getResult() == ColorChooser.OK) bevelPanel1.setBackground(colorChooserTausta.getValue()); } |
void buttonControlOK_actionPerformed(ActionEvent e) {
this.setVisible(false); } |
import dialogit.*;
public class LaskuriFrame extends DecoratedFrame {
} |
void menuItemAbout_actionPerformed(ActionEvent e) {
aboutDialog.show(); } |
Tehtävä
1.4 Modaalinen dialogi Muuta koodi AboutDialog
aboutDialog = new ...
muotoon:
AboutDialog aboutDialog = new AboutDialog(aboutFrame,"Tietoja Autolaskurista",true); |
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ää.
public class Autolaskuri {
boolean packFrame = false; //Construct the application
//Main method
|
//Construct the applet
public LaskuriApplet() { LaskuriFrame frame = new LaskuriFrame(); frame.validate(); frame.setVisible(true); } |
<APPLET
CODEBASE = "." CODE = "LaskuriApplet.class" NAME = "AutolaskuriApplet" WIDTH = 400 HEIGHT = 300 HSPACE = 0 VSPACE = 0 ALIGN = middle > |
...
<APPLET
|
Perus.java - Java perusrakenne |
public class Perus {
static public void main(String[] args) {
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));
if (a > b) {
|
static public void main(String[] args) |
int i = -1;
do { try { i = System.in.read(); } catch (Exception e) {} } while (i == -1); |
Ali.java - aliohjelmat |
import java.io.*;
public class Ali {
try {
return st.nval;
static public int bigger(int a, int b) {
static public double average(int a, int b) {
|
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.
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)
static int montako_mahtuu(int[] luvut, int n, int raja)
static int summaa(int[] luvut, int n)
static void tulosta(int[] luvut, int n)
public static void main(String[] args)
alusta(luvut,TKOKO,3);
|
int luvut[] = new int[]{1,2,3,4,5}; |
int i=0,j=0;
eka: for (i = 0; i < luvut.length; i++){
|
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){
caGraafinenOlio(int x, int y) { paikka(x,y); nakyy = false;
}
final boolean sammuta()
final boolean sytyta()
boolean siirra(int x, int y) {
boolean tulosta(String s) {
public String tasaaOik(String str,int koko) {
public String tasaaVas(String str,int koko) {
}
abstract class caSateellinenOlio extends caGraafinenOlio {
private boolean koko(int r) {
caSateellinenOlio(int x, int y, int r) { super(x,y); this.r
= r; }
boolean tulosta(String s) {
boolean muuta_koko(int r) {
class cPiste extends caGraafinenOlio { cPiste(int x, int y) { super(x,y); }
boolean piirra() {
class cYmpyra extends caSateellinenOlio { cYmpyra(int x, int y, int r) { super(x,y,r); }
boolean piirra() {
public class Oliot { public static void main(String[] argv)
cPiste p1 = new cPiste(),p2 = new cPiste(10,20);
p = new cYmpyra(9,9,9);
kuvat[0] = new cYmpyra(10,10,100);
} |
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 |
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 {
final int BUTTON = 1, LABEL = 2;
//Construct the frame
//Component initialization
this.setLayout(borderLayout);
button.setFont(new Font("Dialog", 0, 10));
// Sisäkkäinen luokka
bevelPanel.setLayout(xYLayout2);
for (i = 0; i < SAIKEITA; i++) {
public void button_mouseClicked(Object o, Object event) {
if (laskuri[i] != null )
laskuri[i] = new cLaskuri(label[i],KIERROKSIA);
saieNro = i; // Sisäkkäiseen
luokkaan ei voi viedä lokaaleja muuttujia!
public void label_mouseClicked(Object event,Object o) {
} class cLaskuri extends Thread {
cLaskuri(Label Text, int raja) {
void lopeta() { loppuu = true; } public void run() {
void count() {
|
Seuraava kuva havainnollistaa tietokantakomponenttien toimintaa JBuilderissa. SQL-palvelin voi periaatteessa olla mikä tahansa ODBC-yhteensopiva tietokanta.
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.
name = navigatorControlPuh
dataSet = queryDataSetPuh |
name = labelControlNimi
background = Yellow dataSet = queryDataSetPuh columnName = NIMI font = "SansSerif", Bold, 18 |
Kuva 3.7 GridBagLayout-ruudukko |
Kuva 3.8 Constraints-dialogi |
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.
FieldControl:
name = fieldControlHakuehto text = 'select * from puh' ButtonControl: name = buttonControlHae label = 'Hae' |
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(); } |
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 |
void gridControlPuh_subfocusChanged(MatrixSubfocusEvent e) {
labelControlNimi.setText(gridControl1.getModel(). get(e.getLocation().row,e.getLocation().column). toString()); } |
name = tabsetPanelPuh
Constraints: Width = 3 Wight/Y = 1 Fill = Both |
name = bevelPanelLomake
constraints = Lomake bevelInner = Flat layout = GridBagLayout |
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
for (i=0; i < queryDataSetPuh.getColumnCount();
i++) {
// Luodaan teksti-kenttä, jossa
on tietokannan kentän nimi
// Luodaan edit-kenttä, jossa on
tietokannan kentän arvo
// Lisätään paneeli, joka "puristaa" edellä
luodut elementit ylälaitaa vasten
void buttonControlHae_actionPerformed(ActionEvent e) {
|
public void setLaskettavat(String newLaskettavat) {
laskettavat = newLaskettavat; } public String getLaskettavat() {
public void setMaara(int newMaara) {
public int getMaara() {
|
void lisaaButton_actionPerformed(ActionEvent e) {
maara = maara + 1; laskuriField.setText(""+maara); } |
public void setLaskettavat(String newLaskettavat) {
lisaaButton.setLabel(laskettavat); laskettavat = newLaskettavat; } |
public void Nollaa() {
maara = 0; laskuriField.setText("0"); } |
void nollaaButton_actionPerformed(ActionEvent e) {
laskuriBean1.Nollaa(); laskuriBean2.Nollaa(); } |
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.
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) ); |
Kuva 5.3 Taulun luominen InterBase-tietokantaan |
|
Kuva 5.5 InterBase 5.0 DSN:n luominen |