Helsingin yliopisto / Tietojenkäsittelytieteen laitos / 581258-1 Johdatus ohjelmointiin
Copyright © 1997 Arto Wikla. Tämän oppimateriaalin käyttö on sallittu vain yksityishenkilöille opiskelutarkoituksissa. Materiaalin käyttö muihin tarkoituksiin, kuten kaupallisilla tai muilla kursseilla, on kielletty.

6.2 Sovelma: piirtämistä (Java 1.0.2)

(Muutettu viimeksi 8.12.1997)

Sovelmia esitellään käyttäen Javan versiota 1.0.2, koska Netscape® Communicator 4.04 -selain (käytössä mm. laitoksen Linux-järjestelmässä) ei osaa Javan versioita 1.1.*.

Versiot 1.1.* eivät poikkea piirtämisen menetelmien osalta paljonkaan 1.0.2:sta: Tämän sivun kaikki esimerkit kelpaavat valituksitta myös kääntäjälle 1.1.3!

Metodi paint(Graphics g)

Edellä esitellyt sovelman metodit metodit start(), stop(), ..., peritään luokasta Applet tyhjinä metodeina ja korvataan tarpeen mukaan haluntunsisältöisinä. Samanlainen on metodi paint(Graphics g).

Sovelman laatija korvaa (overrides) tämän metodin sellaisella, joka piirtää sovelman ikkunan sisällön. (Applet itse perii tämän tyhjän metodin luokalta Component!)

Järjestelmä, joka sovelmaa näyttää, kutsuu paint()-metodia aina, kun näkymä pitää piirtää: sovelman suorituksen alussa, kun näkymä on ollut peitettynä, kun se palautetaan kuvakkeesta ikkunaksi, ... Kutsuva järjestelmä antaa paint()-metodille parametrina Graphics-luokan ilmentymän, joka juuri on sovelman ikkuna. (Kyseessä on itse asiassa Graphics-luokan jonkin aliluokan ilmentymä, koska Graphics on itse abstrakti!)

Luokassa Graphics on määritelty joukko metodeita sovelman ikkunassa näytettävän kuvan muodostamiseen ja käsittelyyn:

Ikkunan koordinaatit ilmaistaan kuvapisteinä (ns. pikseleinä) siten, että ikkunan vasemman yläkulman koordinaatit ovat (0,0), yläkulman alapuolinen pikseli on (0,1), yläkulman viereinen pikseli on (1,0), jne. Jos WWW-sivulla on määritelty vaikkapa

<applet code="HoiSovelma.class" width=250 height=70>,
sovelman ikkunan oikean alakulman koordinaatit ovat (249,69).

Tekstien kirjoittamista ikkunaan

Jo edellisen kappaleen sovelmissa kirjoitettiin ikkunaan tekstejä metodilla drawString(). Uusi esimerkki:
import java.awt.Graphics;

public class Kirjoittelua extends java.applet.Applet {
  public void paint(Graphics g) {
     for (int i=0; i<299; i+=10)
     g.drawString("Böö "+i, i, i);
  }
} 
Sovelma näyttää tällaiselta:

SELAIN EI OSAA JAVAA!

(Tälle sivulle on kirjoitettu seuraava applet-tunniste:
<applet code="Kirjoittelua.class" width=300 height=300>)

Kuten näkyy, tekstin alalaita sijoitetaan annettuun kohtaan. Ensimmäinen rivi ei näy! ("Tekstin alalaita" on sellainen, että esimerkiksi kirjain "j" alittaa sen!)

Luokasta Font löytyy monenlaisia kirjasintyyppejä.

Esimerkki yhdestä kirjasintyypistä ja luokan Font käytöstä (1.1:ssä "TimesRoman"-->"Serif", "Helvetica"-->"SansSerif", "Courier"-->"Monospaced"):

import java.awt.Graphics;
import java.awt.Font;

public class KaunoKirjoittelua extends java.applet.Applet {
  public void paint(Graphics g) {

    Font kirjasin = new Font("TimesRoman", Font.BOLD+Font.ITALIC, 14);
    g.setFont(kirjasin);
    for (int i=0; i<299; i+=15)
      g.drawString("Che bella "+i, i, i);
  }
}
Sovelma näyttää tällaiselta:

SELAIN EI OSAA JAVAA!

(Tälle sivulle on kirjoitettu seuraava applet-tunniste:
<applet code="KaunoKirjoittelua.class" width=300 height=300>)


Laaditaan pikku sovelma, jolla voi tutkia, milloin ja miten usein paint-metodi suoritetaan:
import java.awt.*;

public class PainttiLaskuri extends java.applet.Applet {

  static private int lkm=0;

  public void paint(Graphics g) {
    g.drawString("Maalauskerta numero: "+lkm, 5,15);
    ++lkm;
  }
} 
Ja tältä sovelma näyttää:

Selain ei ymmärrä Javaa!

(Tälle sivulle on kirjoitettu seuraava applet-tunniste:
<APPLET CODE="PainttiLaskuri.class"  WIDTH=200 HEIGHT=20>)

Huom: Netscape lataa sovelman reload-operaatiolla toisinaan virheellisesti kahteen kertaan samaan ikkunaan. Siksi tässä esimerkissä joskus kaksi numeroa piirretään päällekkäin!

Janojen ja geometristen kuvioiden piirtämistä

Graphics-luokassa on määritelty joukko piirtämisvälineitä.

Metodit on määritelty abstrakteina. Graphicsin aliluokat siis itse asiassa toteuttavat nuo välineet omien vaatimustensa mukaisina.

Janoja kuva-alalle pirretään metodilla

drawLine(alkuX, alkuY, loppuX, loppuY)

Esimerkkejä:

Seuraava sovelma piirtää janan ja kirjoittaa päätepisteet (Viiva.html):

 
import java.awt.Graphics;
import java.applet.Applet;

public class Viiva extends Applet {
  public void paint(Graphics g) {
     g.drawRect(0,0,299,199);
     g.drawLine(50,50,250,150);
     g.drawString("(50,50)",25,45);
     g.drawString("(250,150)",225,165);
  }
}

Selain ei ymmärrä Javaa!
(Tälle sivulle on kirjoitettu seuraava applet-tunniste:
<APPLET CODE="Viiva.class"  WIDTH=300 HEIGHT=200>)


Seuraava sovelma arpoo janan paikan (ArpaViiva.html) (Netscapen Reload-operaatio lataa kuvan usein virheellisesti kahteen kertaan päällekkäin. Sovelma kirjoittaa joka maalauskerralla Java-konsolille ilmoituksen. Seuraa konsolia!):

 
import java.awt.Graphics;
import java.applet.Applet;

public class ArpaViiva extends Applet {
  public void paint(Graphics g) {

     System.out.println("maalataan");

     int alkux,alkuy, loppux, loppuy;

     alkux  = (int)(Math.random()*300);
     alkuy  = (int)(Math.random()*200);
     loppux = (int)(Math.random()*300);
     loppuy = (int)(Math.random()*200);

     g.drawRect(0,0,299,199);
     g.drawLine(alkux,alkuy,loppux,loppuy);
     g.drawString("("+alkux+","+alkuy+"),("+loppux+","+loppuy+")",1,12);

  }
}

Selain ei ymmärrä Javaa!
(Tälle sivulle on kirjoitettu seuraava applet-tunniste:
<APPLET CODE="ArpaViiva.class"  WIDTH=300 HEIGHT=200>)


Piirretään sininen sinikäyrä (väreistä kohta lisää) (SiniViiva.html):

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

public class SiniViiva extends Applet {
  public void paint(Graphics g) {
     int x, y;
     g.setColor(Color.blue);
     g.drawRect(0,0,299,99);
     g.drawString("Sini:",3,12);
     g.drawLine(0,50,299,50);
     for (x=1; x<300; ++x) 
       g.drawLine(x, (50+(int)(Math.sin(x/10.0)*30)),
                  x, (50+(int)(Math.sin(x/10.0)*30)));
  }
}
Selain ei ymmärrä Javaa!
(Tälle sivulle on kirjoitettu seuraava applet-tunniste:
<APPLET CODE="SiniViiva.class"  WIDTH=300 HEIGHT=100>)


Myös monenlaisten geometristen kuvioiden piirtoon löytyy välineitä (Kuvioita.html):

 
import java.awt.Graphics;
import java.applet.Applet;

public class Kuvioita extends Applet {
  public void paint(Graphics g) {
     g.drawRect(0,0,299,199);

     g.drawRect(10,10, 20,20);
     g.fillRect(40,10, 20,20);

     g.drawRoundRect(70,10, 40,30, 7, 15);
     g.fillRoundRect(120,10, 30,40, 15, 7);

     g.draw3DRect(160,10, 30,20, true);
     g.draw3DRect(200,10, 15,30, false);

     int[] xPisteet = {70,240,27,166,90,230};
     int[] yPisteet = {50,160,89,198,97,100};
     int pisteLkm = xPisteet.length;
     g.drawPolygon(xPisteet, yPisteet, pisteLkm);

     // on myös fillPolygon, drawOval, fillOval, 
     //         drawArc, fillArc

  }
}

Selain ei ymmärrä Javaa!
(Tälle sivulle on kirjoitettu seuraava applet-tunniste:
<APPLET CODE="Kuvioita.class"  WIDTH=300 HEIGHT=200>)

Huom: Selaimet eivät välttämättä osaa näyttää tuota "3DRectiä" oikein: sen pitäisi näyttää kohokuvalta (true) tai kuopalta (false)

Väreistä

Luokassa Color on värienkäsittelyvälineitä. Siellä on myös vakiot seuraaville väreille: black, blue, cyan, darkGray, gray, green, lightGray, magenta, orange, pink, red, white ja yellow.

Muita värejä voi määritellä ns. RGB-lukukolmikkoina, jotka annetaan Color-konstruktorille. Valkoinen on Color(255,255,255), musta Color(0,0,0), puhdas punainen Color(255,0,0), ...

Esimerkkejä:

Piirretään joukko värillisiä neliöitä (VariNelioita.html):

import java.awt.Graphics;
import java.awt.Color;

public class VariNelioita extends java.applet.Applet {

  public void paint(Graphics g) { 
     g.drawRect(0,0, 139, 139);

     setBackground(Color.white);
     
     g.setColor(Color.blue);;
     g.fillRect(10,10, 20,20);

     g.setColor(Color.green);;
     g.fillRect(30,30, 20,20);

     g.setColor(Color.orange);;
     g.fillRect(50,50, 20,20);

     g.setColor(Color.pink);;
     g.fillRect(70,70, 20,20);

     g.setColor(Color.red);;
     g.fillRect(90,90, 20,20);

     g.setColor(Color.yellow);
     g.fillRect(110,110, 20,20);

  }
}

Selain ei ymmärrä Javaa!
(Tälle sivulle on kirjoitettu seuraava applet-tunniste:
<APPLET CODE="VariNelioita.class"  WIDTH=140 HEIGHT=140>)


Käydään läpi RGB-määriteltyjä värejä (käydään läpi R- ja G-arvoja, B-komponentti arvotaan joka maalauskerralla, koska tasossa on vain kaksi ulottuvuutta) (OmatVarit.html):

import java.awt.Graphics;
import java.awt.Color;

public class OmatVarit extends java.applet.Applet {

  public void paint(Graphics kuva) { 
     kuva.drawRect(0,0, 277, 277);
     setBackground(Color.white);

     int r,g,b; // RGB värikolmikko

     b = (int)(Math.random()*256);

     for (r=0; r<256; r+=3) 
       for (g=0; g<256; g+=3) {
         Color vari = new Color(255-r,255-g,b);
         kuva.setColor(vari);
         kuva.fillRect(10+r,10+g, 3,3);
       }
  }
}
Selain ei ymmärrä Javaa!
(Tälle sivulle on kirjoitettu seuraava applet-tunniste:
<APPLET CODE="OmatVarit.class"  WIDTH=278 HEIGHT=278>)

Yllä värejä piirretään 3x3-neliöihin ja RG-arvoissa edetään kolmen välein. Pikselittäin piirtäen tulos on aika mukavan näköinen, mutta kestää kauan: OmatVarit2.html, Omatvarit2.java.

(Yksi mielestäni kaunis esimerkki värien tulostamisesta löytyy sivultani "Coloured rectangles in a square")


Takaisin luvun 6 sisällysluetteloon.