Ilkka Koivistoinen 13.02.2002

Edellinen

Seuraava

10.3 Appletin ikkunan hallinta - Piirto

Graphics -luokan metodeilla voidaan applettin käyttämään ikkunaan piirtää

merkkijonoja
viivoja
pisteitä
tasokuvia
etukäteen määritettyjä graafisia olioita (painikkeet, teksti-ikkunat jne..)
valmiita bittikarttoja (gif, jpg)
Graphics2D -luokan metodeilla voidaan lisäksi tehdä muutakin

Aloitetaan kuitenkin määrittelemällä piirtopinta. Se muodostuu siitä suorakaiteesta, joka on määritetty html:n applet -tagin width ja height -parametreissa. Suorakaide asetetaan siihen kohtaan näyttöä, kuin se ympäröivän html -sivun asetusten ja selaimen ikkunan koon ja paikan mukaisesti sattuu asettumaan. Huomaa, että piirtopinta  liukuu selaimen pinnalla, mikäli käyttäjä vierittää ikkunan sisältöä hissillä tai metrolla (siis pystysuoralla tai vaakasuoralla vierityspalkilla). Suorakaide ei siis ole absoluuttisesti tietyssä kohdin näytön pintaa. Mikäli selaimen ikkuna on pienempi, kuin vaadittu appletin piirtopinta, piirtopinta katkeaa kesken. Osa appletista piirtyy tällöin selaimen ikkunan ulkopuolelle näkymättömiin. Kokonaisuudessann tätä piirtopintaa sanotaan appletin ikkunaksi. (Piirtopintaa sanotaan myös nimellä paneeli. Mikäli paneeleja ei ole erikseen määritelty, koko piirtopinta muodostaa yhden paneelin. Määrittelemällä useampia paneeleja, on piirtopinta mahdollista jakaa osiin (alipaneeleihin). Tähän graafisten objektien sijoittelun kannalta varsin keskeiseen asiaan palaamme kuitenkin vasta seuraavalla java -kurssilla.)

Appletin ikkuna eli lyhyesti tässä yhteydessä ikkuna muodostaa suorakulmaisen koordinaattijärjestelmän siten, että origo on ikkunan vasemmassa yläkulmassa ja x -akseli kasvaa oikealle ja y -akseli alas. Mitat ovat näytön kuvapisteinä eli pikseleinä. (Normaalilla svga -näytöllä on 800 pikseliä vaakasuorassa ja 600 pikseliä pystysuorassa (tämä toki riippuu käyttämistäsi asetuksista)). Piste (x,y) = (20,40) on siis ikkunan vasemmasta ylänurkasta 20 pikseliä oikealle ja 40 pikseliä alas. Kun ikkuna syystä tai toisesta siirtyy näytöllä, siirtyy myös piste (20,40), siten, että etäisyys ikkunan vasempaan ylänurkkaan koko ajan säilyy. Seuraavassa appletissa on väritetty piste (20,40) mustalla (katso tarkkaan). Kun nyt siirrät ikkunaa tai vierität ikkunan sisältöä, pisteen paikka säilyy ikkunan (tässä tapauksessa oikealla puolella olevan 60 kertaa 60 pikselin kokoinen) vasemman ylänurkan suhteen. Appletti ei näy

Seuraavaksi voimmekin käydä läpi kaikki tärkeimmät piirtotyökalut. Ne on esimerkkiappleteissa kirjoitettu paint() -metodiin. Tässä suhteessa kannattaa olla tarkkana, kuten myöhemmin huomataan.

10.3.1 Merkkijonon piirto

Merkkijono piirretään Graphics luokan olion drawString(String s, int x, int y) -metodilla. Metodilla on kolme parametria. Merkkijono s piirretään ikkunaan siten, että vasemmanpuolimmaisen merkin vasen alakulma tulee ikkunan pikseliin (x,y). (Tarkasti ottaen paikka määräytyy käytetyn fontiston kirjaimen vasemaan alanurkan mukaisesti. Oheisessa kuvassa on esitetty ko. paikka T -kirjaimelle)

wpe17.jpg (3098 bytes)

Merkkijonon kirjoittamisesta meillä onkin ollut jo esimerkkejä aiemmin. Merkkijonon kirjaimisto, korostus ja korkeus pikseleinä määrätään Font -luokan oliota muodostettaessa tai  setFont() -metodilla. Väri määrätään  setColor()-metodilla. Värin määrittelyyn palaamme myöhemmin. Käytettävän fontin ja kirjoittetavan merkkijonon dimensiot selvitetään stringWidth(String), charWidth(char) ja getHeight() -metodeilla. Metodeja käytetään seuraavasti. Olkoot meillä asetettu jokin Font -olio f ja Graphics -olio ikkuna.

FontMetrics fm = getFontMetrics(f); // Määritellään olio fm, joka luodaan fontiston f perusteella.
ikkuna.setFont(f); // asetetaan fontisto f käyttöön
String s =  "Pieksämäen asemalla blues";
int  jononPituus = fm.stringWidth(s);
int merkistönKorkeus = fm.getHeight();

10.3.2 Viivan piirto

Viivat piirretään drawLine(int x1, int y1, int x2, int y2) -metodilla, joka piirtää viivan pisteestä (x1,y1) pisteeseen (x2,y2).  Piirtoväri määräytyy setColor() -metodilla (johon palataan myöhemmin). Seuraava esimerkki piirtää viivoja satunnaisiin paikkoihin ikkunasa satunnaisilla väreillä.

Esimerkki 54.

import java.util.Random;
import java.awt.*;
public class E54 extends java.applet.Applet {
// Satunnaislukuja ikkunan alueelta ja näin saatujen pisteiden yhdistelemistä viivoilla
  Font f = new Font("Verdana",Font.BOLD,12);
  public void paint(Graphics screen) {
     screen.setFont(f);
     screen.setColor(Color.red);
     screen.drawString("Satunnaislukuja",5,10);
     Random x = new Random();
     int x1,x2,y1,y2,v1,v2,v3;
     x1=(int)(x.nextDouble()*799); y1=(int)(x.nextDouble()*389)+11;
     for (int i=1;i<1000000;i++) {
       if (i%1000 == 0){
         screen.setColor(getBackground());   // Älä välitä vielä getBacground() -metodista
         screen.fillRect(100,0,200,10);  // tämä on vain luvun muuttumista varten. Älä siis välitä tästä
         screen.setColor(Color.black);
         screen.drawString(" "+i,100,10);
       }
       x2=(int)(x.nextDouble()*799); y2=(int)(x.nextDouble()*389)+11;
       v1=(int)(x.nextDouble()*256);
       v2=(int)(x.nextDouble()*256);
       v3=(int)(x.nextDouble()*256);
       Color c1 = new Color(v1,v2,v3);   // väri on RGB -väri. Palaamme asiaan myöhemmin
       screen.setColor(c1);
       screen.drawLine(x1,y1,x2,y2);  // Jos ajat applettia appletviewerissä, voit käyttää system.out.printl; komentoa
// jolloin dos -ikkunaan tulostuu tekstiä, kuten kurssin alkuosassa opittiin. Tämä on hyvä tapa testata ohjelmia,
//  mutta lopullisessa ohjelmassa onneton tapa sotkea käyttäjä
// screen.drawString(x1+" "+y1+" "+x2+" "+y2,5,10+12*i);
       x1=x2; y1=y2;
     }
  }
}

Tuloksena on seuraavanlainen appletti. (Se on omassa ikkunassaan sen takia, että se varastaa kaiken prosessoriajan ja jumiuttaa järjestelmän. Tälläisiä tilanteita varten opettelemme myöhemmin ohjelmien säikeistämisen. Lisäksi esimerkki E54 on huonosti kirjoitettu, koska satunnaislukujen arvonta yms. olisi voitu tehdä start() -metodissa ja välittää luokan jäsenmuuttujilla paint() -metodille. Voit tehdä paremman version harjoituksena, kunhan opettelemme asiaa lisää.)

10.3.3 Suorakulmiot

Suorakulmiot piirretään drawRect() tai fillRect() -metodeilla. Edellinen piirtää suorakaiteen ääriviivat ja jälkimmäinen piirtää ääriviivat ja täyttää tämän jälkeen suorakaiteen. Molemmat metodit tarvitsevat neljä parametria.

suorakulmion vasemman yläkulman x ja y -koordinaatit
suorakulmion leveyden ja
suorakulmion korkeuden

Seuraavassa appletissa E55 piirretään suorakaide jonka leveys on 200, korkeus 100 ja vasen yläkulma paikassa (10,50). Suorakaide syntyy komennolla

ikkuna.drawRect(10,50,200,100); tai

ikkuna.fillRect(10,50,200,100);

Oletustäyttövärinä on musta.

Suorakulmion reunoja voi myös pyöristää drawRoundRect() tai fillRoundRect() -metodeilla. Pyöristys tehdää asettamalla suorakulmion vasempaan yläkulmaan suorakulmion, jonka leveys ja korkeus on x ja y. Tämän jälkeen pyöristetään kulma sopivasti xy -suorakulmion lävistäjällä. Viereisen appletin E55 alin kuvio on tehty komennolla

ikkuna.drawRoundRect(10,140,200,50,50,10); .

10.3.4 Monikulmio

Monikulmio piirretään drawPolygon() -metodilla. Se saa yhden ainoa parametrin, joka on tyyppiä Polygon. Polygon -olio luodaan seuraavasti

int x[] = { 10, 20, 90, 60, 25 }; // monikulmion kärkien x-koordinaatit
int y[] = { 10, 90, 80, 55, 5 }; // monikulmion kärkien y -koordinaatit
int points = x.length; // monikulmion kärkien määrä
Polygon poly = new Polygon(x,y,points);

Kun Polygon olio on luotu, voidaan kuvio piirtää drawPolygon(poly) - tai fillPolygon(poly) -metodeilla.

Ohessa appletti E56, joka on piirretyy yllä olevilla arvoilla. Jos monikulmioon halutaan lisätä jälkikäteen pisteitä, se voidaan tehdä addPoint() -metodilla. Monikulmion ensimmäisen ja viimeisen pisteen ei tarvitse olla välttämättä samat. Monikulmio suljetaan automaattisesti, kuten viereisestä appletista nähdään.

10.3.5  Soikiot ja kaaret

Soikiot muodostetaan drawOval() tai fillOval() -metodeilla. Soikio muodostetaan samaan tapaan, mitä suorakaiteen kulmat pyöristettiin. Toisin sanoen annetaan ikkunasta suorakaide ja sitten soikion leveys ja korkeus (ympyrälle soikion leveys ja korkeus ovat samoja).

Viereisessa appletissa E57 on piirretty soikioita ja ympyröitä seuraavilla silmukoilla

for (int i=10; i<50; i+=10) ikkuna.drawOval(20,40,i,10+i); // soikiota
for (int i=10; i<50; i+=10) ikkuna.drawOval(120,20,i,i);  // ympyröitä

Kaaret piirretää soikioiden osana. Käyttämällä yksikköympyrästä saatua kulman vaihetta ja merkkisopimusta (siis positiivisen x-akselin suhteen vastapäivään laskettu kulma) voidaan soikion kaari piirtää aloituskulman arvosta lopetuskulmanarvoon. Kulman yksikkönä käytetään asteita. Metodikutsu on seuraavanlainen

ikkuna.drawArc(x,y,leveys,korkeus, aloituskulma, lopetuskulma); // kaikki parametrit tyyppiä int

Neljä ensimmäistä parametria ovat samoja kuin soikioissa. Kaksi viimeistä parametria määrää kaaren piirtämisen aloitus ja lopetusasteluvut (jotka voivat olla myös negatiivisia tai sisältää useamman kierroksen). Esimerkki 57 on kirjoitettu esimerkkiin E58 seuraavasti

for (int i=10; i<50; i+=10) ikkuna.drawArc(20,40,i,10+i,-90+i, 180-i); // soikion kaaria
for (int i=10; i<50; i+=10) ikkuna.drawArc(120,20,i,i,-90+ii, 180-i);  // ympyrän kaaria

10.3.6 Suorakulmion kopiointi ja leikkaaminen

Graphics -luokassa on kaksi metodia piirretyn alueen käsittelyyn.

copyArea() kopioi annetun suorakulmion muotoisen alueen toiseen paikkaan
clearArea() kumittaa suorakulmion muotoisen alueen siten, että jäljelle jää taustan väri.

copyArea() -metodille annetaan kuusi parametria. Neljä ensimmäistä ovat kuten drawRect() -metodissa. Kaksi viimeistä on kopion sijainnin paikka x ja y -suunnassa.

clearArea() -metodilla on neljä parametria, kuten drawRect() -metodilla.

Esimerkiksi lauseella

ikkuna.clearRect(0,0,getSize().width,getSize().height);

voidaan tyhjentää koko ikkuna. getSize() -metodi palauttaa Dimension olion, joka koostuu kahdesta luvusta (ikkunan leveys, ikkunan korkeus) joihin viitataan   jäsenmuuutujilla width ja height.

Seuraavalla pikku kikalla saa keskitettyä merkkijonon s ikkunaan. Olkoot määritelty Font -olio f ja Graphics -oli ikkuna.

FontMetrics fm = getFontMetrics(f); // Määritellään olio fm, joka luodaan fontiston f perusteella.
ikkuna.setFont(f); // asetetaan fontisto f käyttöön
String s =  "Pieksämäen asemalla blues";
int  x = (getSize().width-fm.stringWidth(s)) / 2;
int y = getSize().height / 2;
ikkuna.DrawString(s,x,y);

10.3.7 Väri

Java käyttää värin muodostuksessa RGB -metodia, jossa jokaista värin komponentti vastaa kirkkausaste 0 - 255 (ts. värin kirkaus määräytyy 8 bitillä). Väri luodaan seuraavasti

Color c1 = new Color(255,204,102);

Tämän jälkeen väri astetaan voimaan Graphics -oliolle ikkuna lauseella

ikkuna.setColor(c1);

Nyt seuraava piirto -olio, joka luodaan tehdään asetetulla värillä.

Seuraavat värit on valmiiksi määritelty ja niitä voi käyttää milloin vain

black
(0,0,0)
blue (0,0,255) cyan (0,255,255) darkGray (64,64,64) gray (128,128,128) green (0,255,0) lightGray (192.192,192)
magenta (255,0,255) orange (255,200,0) pink (255,175,175)

red
(255,0,0)

white (255,255,255) yellow (255,255,0)  

Väripaletti näyttää tältä. Värit ovat samassa järjestyksessä, mitä ne on lueteltu edellisessä taulukossaa (E59.java)

Valmiiksi määritellyt värit saa aikaan asettamalla

ikkuna.setColor(Color.pink);

Taustan väriksi voi määrittää setBackground() -metodilla vaikka värin green seuraavasti

setBackground(Color.green);

Ja jos pääsee unohtumaan, mikä olikaan taustan väri, saa sen selville metodilla getBackground(). Piirtovärin saa selville vastaavsti getColor() -metodilla.

Piirto-objektien lisäksi ikkunassa saattaa olla käyttöliittymäkomponentteja. Niiden väreihin pääsee käsiksi setForeground() ja getForeground() -metodeilla.

10.3.8 Tehtäviä

  1. Tee appletti, joka piirtää punaisia palloja ja soikioita siniselle pohjalle. Pallojen ja soikioiden paikat ja värit voit  päättää itse. Vastaus
  2. Tee appletti, joka piirtää tukkimiehen kirjanpitoa (tee ensin luokka, jonka metodi piirtää viiden ryhmän sekä metodi, joka piirtää halutun määrän viivoja 1 - 4. Laita paint() -metodiin kutsu, jossa kerrotaan, minne eo. piirto-oliot piirretään. Lopuksi sovella tehtävää piirtämällä tukkimiehen kirjanpidolla luku 27. Vastaus
  3. Tee appletti, joka piirtää yhden lottoruudukon (numeroita lienee 39 ja väritetyn ympyrän sisään kierroksen numeron. Olkoon se 12). Vastaus
  4. Tehtävä 97*. Tee appletti, joka piirtää vakioveikkaussarakkeen ja arpoo siihen rivin.

Ilkka Koivistoinen 13.02.2002

Edellinen

Seuraava