JAVA SWING GUI -HARJOITUKSET



Samankaltaiset tiedostot
Java-opiskelumateriaali: HARJOITUKSET

JAVA FX GUI -HARJOITUKSET

JAVA FX GUI -HARJOITUKSET

Scratch ohjeita. Perusteet

JAVA on ohjelmointikieli, mikä on kieliopiltaan hyvin samankaltainen, jopa identtinen mm. C++

KUVAN TUOMINEN, MUOKKAAMINEN, KOON MUUTTAMINEN JA TALLENTAMINEN PAINTISSA

HARJOITUKSIA ios-ohjelmointiin LIITTYEN

Avaa ohjelma ja tarvittaessa Tiedosto -> Uusi kilpailutiedosto

Oliosuuntautuneita apletteja

Ohjeissa pyydetään toisinaan katsomaan koodia esimerkkiprojekteista (esim. Liikkuva_Tausta1). Saat esimerkkiprojektit opettajalta.

Muistitikun liittäminen tietokoneeseen

Pong-peli, vaihe Koordinaatistosta. Muilla kielillä: English Suomi. Tämä on Pong-pelin tutoriaalin osa 2/7. Tämän vaiheen aikana

Pong-peli, vaihe Aliohjelmakutsu laskureita varten. 2. Laskurin luominen. Muilla kielillä: English Suomi

Jypelin käyttöohjeet» Ruutukentän luominen

2.1 Yksinkertaisen geometrian luonti

Kirjan toteutus BoD easybook -taittotyökalun avulla

GREDDY PROFEC B SPEC II säätäminen

Tekstieditorin käyttö ja kuvien käsittely

OpenOffice.org Impress 3.1.0

LUKU 17 MUUTAMIA JAVA FX -SOVELLUKSIA. Tässä dokumentissa esitellään muutamia Java FX -sovelluksia.

Labyrintti. Pelihahmon toiminta. Piirrä pelihahmo (älä piirrä esim. sivusta, ettei hahmon tarvitse

SMART Board harjoituksia 09 - Notebook 10 Notebookin perustyökalujen käyttäminen 2 Yritä tehdä tehtävät sivulta 1 ilman että katsot vastauksia.

Tasohyppelypeli. Piirrä grafiikat. Toteuta pelihahmon putoaminen ja alustalle jääminen:

GeoGebra-harjoituksia malu-opettajille

Sen jälkeen Microsoft Office ja sen alta löytyy ohjelmat. Ensin käynnistä-valikosta kaikki ohjelmat

NAP: Merenkulun reitti- ja aikataulueditorin käyttöohje

1. Taustatietoa näppäimistönkuuntelusta

Peilaus pisteen ja suoran suhteen Pythonin Turtle moduulilla

Matikkaa KA1-kurssilaisille, osa 3: suoran piirtäminen koordinaatistoon

Taulukot. Jukka Harju, Jukka Juslin

HARJOITUKSIA ANDROID-OHJELMOINTIIN LIITTYEN

CEM DT-3353 Pihtimittari

BlueJ ohjelman pitäisi löytyä Development valikon alta mikroluokkien koneista. Muissa koneissa BlueJ voi löytyä esim. omana ikonina työpöydältä

ISIS Draw (Windows versio 2.5)

Käyttöliittymän muokkaus

Pong-peli, vaihe Aliohjelman tekeminen. Muilla kielillä: English Suomi. Tämä on Pong-pelin tutoriaalin osa 3/7. Tämän vaiheen aikana

Tietosuoja-portaali. päivittäjän ohje

Python-ohjelmointiharjoituksia

20. Javan omat luokat 20.1

Sisällys. 20. Javan omat luokat. Java API. Pakkaukset. java\lang

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo

NÄIN TEET VIDEO-MAILIN (v-mail)

Sukelluskeräily, Pelihahmon liikuttaminen. Tee uusi hahmo: Pelihahmo. Nimeä se. Testaa ikuisesti -silmukassa peräkkäisinä testeinä (jos) onko jokin

GEOS 1. Ilmastodiagrammi Libre Office Calc ohjelmalla

Jypelin käyttöohjeet» Miten saan peliin pistelaskurin?

TALLENNETAAN MUISTITIKULLE JA MUISTIKORTILLE

Jypelin käyttöohjeet» Ruutukentän luominen

Gimp 3. Polkutyökalu, vektori / rasteri, teksti, kierto, vääntö, perspektiivi, skaalaus (koon muuttaminen) jne.

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

TIETOKONEEN ASETUKSILLA PARANNAT KÄYTETTÄVYYTTÄ

Matopeli C#:lla. Aram Abdulla Hassan. Ammattiopisto Tavastia. Opinnäytetyö

Venekilpailu! Esteiden väistely ja hahmon ohjaaminen

1 Asentaminen. 2 Yleistä ja simuloinnin aloitus 12/

UpdateIT 2010: Editorin käyttöohje

KODU. Lumijoen peruskoulu

Ponnahdusikkunoiden ja karttatekstien hallitseminen ArcGIS Online kartoissa

1 ClipArt -kuvan käyttö Paint-ohjelmassa

Java ja grafiikka. Ville Sundberg

Ajokorttimoduuli Moduuli 2. - Laitteenkäyttö ja tiedonhallinta. Harjoitus 1

TALLENNETAAN MUISTITIKULLE JA MUISTIKORTILLE

Ohjeita peda.net palvelun Luo uusi osioon

Konfiguraatiotyökalun päivitys

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

Ohjelmointi 2 / 2010 Välikoe / 26.3

17. Javan omat luokat 17.1

Kun olet valmis tekemään tilauksen, rekisteröidy sovellukseen seuraavasti:

2. Lisää Java-ohjelmoinnin alkeita. Muuttuja ja viittausmuuttuja (1/4) Muuttuja ja viittausmuuttuja (2/4)

Kirjoita oma versio funktioista strcpy ja strcat, jotka saavat parametrinaan kaksi merkkiosoitinta.

Taulukot Päivi Vartiainen 1

Posterin teko MS Publisherilla

Alkuarvot ja tyyppimuunnokset (1/5) Alkuarvot ja tyyppimuunnokset (2/5) Alkuarvot ja tyyppimuunnokset (3/5)

KOKO PERHEEN HAUSKA STRATEGIAPELI OHJEET

Valitse aineisto otsikoineen maalaamalla se hiirella ja kopioimalla (Esim. ctrl-c). Vaihtoehtoisesti, Lataa CSV-tiedosto

Luento 6. T Ohjelmoinnin jatkokurssi T1 & T Ohjelmoinnin jatkokurssi L1. Luennoitsija: Otto Seppälä

sivu 1 Verkkopäätteen muuttaminen Anvian uuteen tekniikkaan Ohje käy seuraaviin verkkopäätteisiin

Sisältö. 2. Taulukot. Yleistä. Yleistä

811312A Tietorakenteet ja algoritmit , Harjoitus 2 ratkaisu

Käyttöopas RoofCon Viewer

PERUSLASKUJA. Kirjoita muuten sama, mutta ota välilyönti 4:n jälkeen 3/4 +5^2

Dia Diagram Editor. Petri Sallasmaa, Petri Salmela. 20. lokakuuta 2014

6.1 Tekstialueiden valinta eli maalaaminen (tulee tehdä ennen jokaista muokkausta ym.)

PURPLE PEN OHJELMAN KÄYTTÖ Tiedoston avaaminen

Ohje tekstinkäsittelyharjoitus 10. Pöytäkirja, jossa käytetään ylätunnistetta. Tehtävän aloitus

VERKKOVELHO-YLLÄPITOTYÖKALUN KÄYTTÖOHJE

Olio-ohjelmointi Javalla

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

Sisältö. 22. Taulukot. Yleistä. Yleistä

Kuvien lisääminen ja käsittely

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä

Sukelluskeräily. Pelihahmon liikuttaminen. Aarre ja pisteet

Artikkelien muokkaaminen sekä sisältöeditorin peruskäyttö

ITKP102 Ohjelmointi 1 (6 op)

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

12. Javan toistorakenteet 12.1

ELOKUVATYÖKALUN KÄYTTÖ ANIMAATION LEIKKAAMISESSA. Kun aloitetaan uusi projekti, on se ensimmäisenä syytä tallentaa.

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

Tehtävä 3 ja aikakausilehden kansi pastissi 4. runokirjan kansi

SeaMonkey pikaopas - 1

5. Alaindeksi 6. Yläindeksi 7. Poista muotoilut 8. Tasaa teksti vasemmalle

Transkriptio:

JAVA SWING GUI -HARJOITUKSET Tässä dokumentissa olevat Java-harjoituset liittyvät GUI-ohjelmiin, mikä tarkoittaa että ohjelmissa on Graphical User Interface eli graafinen käyttöliittymä. Näissä harjoituksissa graafinen käyttöliittymä perustuu Java Swing -luokkiin. Kari Laitinen http://www.naturalprogramming.com 2015-01-04 Tiedosto luotu. 2015-01-13 Viimeisin muutos 1 Kari Laitinen

OHJEITA HARJOITUSTEN TEKOON Nämä harjoitukset ovat pääsääntöisesti sellaisia, että alussa otetaan käyttöön jokin esimerkkiohjelma, jota muutetaan ja edelleenkehitetään harjoituksissa. Jokaiseen harjoitukseen kuuluu yleensä monta osatehtävää. Tarkoitus on että yhdellä harjoituskerralla tehdään aina johonkin yhteen ohjelmaan liittyvät tehtävät. JCreatorilla työskenneltäessä ei ole tarpeellista perustaa projekteja. Riittää kun.java tiedostot avataan sellaisenaan JCreatoriin ja tarvittavat tiedostot ovat kaikki samassa kansiossa. Varo antamasta Java-ohjelmallesi esim. nimeä String.java, koska String on Javan standardiluokka. Anna ohjelmallesi mieluiten pitkähkö nimi tyyliin KivaPeliHarjoitus.java. Muista myös että Javassa on sääntö jonka mukaan ohjelman pääluokan nimi tulee olla KivaPeliHarjoitus jos tiedostonimi on KivaPeliHarjoitus.java. Säädä ohjelmaeditorisi sellaiseksi että tabulointinäppäimen painallus vastaa kolmea välilyöntiä. Tällaista ohjelmointityyliä on käytetty Kari Laitisen esimerkkiohjelmissa joita näissä harjoituksissa muutellaan. Paras on säätää editori sellaiseksi että tabulointimerkin tilalle tiedostoon tulee kolme välilyöntiä. (Yleensä editoreissa on Settings- tai Configure-menu josta tämmöisen säätämisen voi tehdä.) 2 Kari Laitinen

HARJOITUKSIA OHJELMALLA HelloApplet.java Muista että aplettiharjoituksia tehdessä tarvitset aina.html -tiedoston, joka määrittelee sivun jossa apletti toimii. 1. Ota pohjaksi "HelloApplet.java" ja muuta ohjelma sellaiseksi että se tulostaa apletille varatulle sivun osalle laskevat portaat seuraavaan tyyliin Portaat voi tietysti piirtää jokaisen erikseen kutsumalla metodia drawline() riittävän monta kertaa, mutta suositus on että piirrät portaat kutsumalla drawline()-metodia silmukassa. paint()-metodin rakenne voi olla seuraavan tapainen 3 Kari Laitinen

int viivan_alkupiste_x = 10 ; int viivan_alkupiste_y = 10 ; while (... { graphics.drawline( viivan_alkupiste_x, viivan_alkupiste_y,... // vaakaviivan piirto viivan_alkupiste_x = viivan_alkupiste_x + 30 ; graphics.drawline( viivan_alkupiste_x, viivan_alkupiste_y,... // pystyviivan piirto } viivan_alkupiste_y = viivan_alkupiste_y + 30 ; paint()-metodissa voi tietysti käyttä esim muuttujaa int porraslaskuri = 0 ; jolla lasketaan piirrettyjen portaiden lukumäärää ja kontrolloidaan silmukan päättyminen. 4 Kari Laitinen

2. Lisää portaat piirtävään silmukkaan kutsu Graphics -luokan metodiin fillrect() siten että portaiden alle "perustukseksi" piirtyy joukko täytettyjä suorakaiteita alla esitetyllä tavalla. drawrect() -metodilla saat halutessasi suorakaiteille ääriviivat. Perustus kannattaa piirtää eri värillä kuin portaiden ääriviivat. EarthAndMoonApplet.java -ohjelmasta näet miten piirrosväri voidaan tarvittaessa muuttaa setcolor() -metodilla. fillrect() -metodi on käytössä esimerkiksi GrafiikkademoApplet.java-ohjelmassa. Kuva on sikäli virheellinen, että paksumman viivan piirtämiseen ei ole olemassa omaa metodia.. 5 Kari Laitinen

3. Määrittele aplettiluokkaan seuraava datajäsen int maalauslaskuri = 0 ; Kun lisäät paint()-metodiin lauseet maalauslaskuri ++ ; graphics.drawstring( "Maalattu " + maalauslaskuri + " kertaa.", 150, 10 ) ; voit havaita että maalauslaskurin arvo kasvaa esimerkiksi kun pienennät ja taas suurennat apletin ikkunaa. paint()-metodia siis kutsutaan aina kun apletin ikkuna muuttuu suureksi. Tehtäväsi on em. lisäysten jälkeen muuttaa apletti sellaiseksi että ensimmäisellä kerralla ruutua maalattaessa ensimmäisen portaan kohdalle piirretään pallo seuraavaan tapaan. Tässä portaita on vain neljä, mutta sinun ohjelmassa niitä saa olla enemmän.. Kun apletin ikkuna pienennetään ja suurennetaan tulee pallon siirtyä aina yhtä alemmalle portaalle paint()-metodin kutsun seurauksena. Alimman portaan kohdalta pallo siirtyy taas ylimmän portaan kohdalle. (Tässä tehdään eräänlaista käsikäyttöistä animaatiota.) 6 Kari Laitinen

4. Metodin setcolor() kutsulla graphics.setcolor( new Color( viivan_alkupiste_y * 0x10000 ) ) ; portaiden "perustuspalkit" saadaan piirtymään punaisen eri sävyillä. Tutki luokkaa Color ja ota selville miten eri palkit tehdään vihreän tai sinisen eri sävyillä. 5. Paranna aplettia vielä siten että se ottaa selville apletille varatun alueen koon y-suunnassa, ja piirtää täsmälleen 7 porrasta kyseiselle alueelle. Piirrettävän pallon halkaisija tulee olla täsmälleen 3/4 portaan korkeudesta. (Kannattaa tutkia ohjelmaa GrafiikkademoApplet.java) Aplettiin on myös mahdollista lisätä System.out.print()-metodin kutsuja, jotka tulostavat tekstiä AppletViewerin avaamaan komentorivi-ikkunaan. Näitä kutsuja voi käyttää esimerkiksi kun haluaa seurata joidenkin muuttujien arvojen muuttumista ohjelman suorituksen aikana. 7 Kari Laitinen

HARJOITUKSIA OHJELMALLA SinglePictureApplet.java Ota käyttöön ohjelma SinglePictureApplet.java ja sille tehty.html-tiedosto. Lisäksi tarvitset ohjelman käyttämän kuvatiedoston jonka löydät kansiosta www.naturalprogramming.com/ javagui/. Harjoitus 1: Tee ohjelmasta SinglePictureApplet.java sellainen että kuva piirretään vain yhteen kertaan, sen luonnollisessa koossa, siten että kuva tulee täsmälleen apletin alueen keskelle. Tässä voit käyttää jotain muutakin kuvaa kuin ohjelman alunperin käyttämää kuvaa. Tässä täytyy ottaa selville apletin leveys ja korkeus. Voit kopioida tarvittavat datajäsenet ja niiden tarvitsemat alustukset esim. ohjelmasta DrawingDemoApplet.java. drawimage()-metodille annetaan parametreinä kuvan vasemman yläkulman paikka. Joudut siis tekemään laskutoimituksia jotta saat vasemman yläkulman sellaiseen paikkaan että kuva tulee alueen keskelle. (Huom! Kuvatiedostoissa on joskus esiintynyt ongelmia siten että jokin kuva ei vaan suostu näkymään. Kokeile siis jotain toista kuvatiedostoa jos kuvan näkymisessä esiintyy jotain mystisyyttä.) 8 Kari Laitinen

Harjoitus 2: Lisää ominaisuus että kuvalle piirretään raamit jollain värillä. Raamit saat kätevästi aikaiseksi kun ennen kuvan piirtoa teet fillrect()-metodilla täytetyn suorakaiteen kuvan alle. Tuon suorakaiteen tulee olla hiukan kuvaa isompi, jotta raamit jäävät sopivasti näkyviin kun kuva piirretään suorakaiteen päälle. Harjoitus 3: Tee ikkunassa näkyvän kuvan taustalle tiiliseinä. Tarkoitus on että tiiliseinä piirretään ennenkuin kuvan raameja tai itse kuvaa piirretään. Tiiliseinän saat aikaiseksi kun ensin täytät koko apletin alueen fillrect()-metodilla sellaisella värillä joka on tiilien välissä olevan laastin väri. Kun olet värittänyt taustalle laastin voit piirtää tiiliä silmukoiden avulla siten että tiilien väliin jää hiukan tyhjää, joka on siis sitä "laastia". Tiilien piirtämiseksi voi käyttää seuraavalla sivulla hahmoteltua silmukkarakennetta, jonka voit kopioida ja täydentää toimivaksi ohjelmaksi. Kun ruudulle piirretään, ei haittaa vaikka piirtäminen tapahtuu varsinaisen piirtoalueen ulkopuolle. Sellaiset piirrokset eivät vaan tule käyttäjälle näkyviin. Näin esim. puolikas tiili voidaan piirtää kun pannaan x-koordinaatti tiilirivin alussa negatiiviseksi, jolloin osa tiilestä piirtyy käyttäjälle näkymättömäksi. 9 Kari Laitinen

graphics.setcolor( new Color( 0xD0, 0x91, 0x32 ) ) ; // tiilien väri int brick_position_x = 0 ; // Eka tiili piirretään vasempaan yläkulmaan int brick_position_y = 0 ; int brick_height = 28 ; // tiilen korkeus int brick_length = 112 ; // tiilen pituus int gap_between_bricks = 4 ; // Tämä on se laastin paksuus. int row_counter = 0 ; // Tällä lasketaan tiilirivejä. while ( brick_position_y < applet_height ) { while ( brick_position_x < applet_width ) { graphics.fillrect( brick_position_x, brick_position_y, brick_length, brick_height ) ; // Tiilen piirto } // Tässä pitäisi kasvattaa tiilen paikan x-koordinaattia sopivasti. // Tiilirivi on piirretty. Valmistaudutaan seuraavan rivin piirtoon. row_counter ++ ; if ( row_counter % 2 == 1 ) // Onko pariton tiilirivi? { // Tässä pitäisi tiilen paikan x-koordinaatti pistää puolen // tiilen verran negatiiviseksi. } else { // Tässäkin pitäisi x-koordinaattia asettaa. } } // Tässä pitäisi tiilen paikan y-koordinaattia muuttaa sopivasti. 10 Kari Laitinen

Kun tämä osatehtävä on suoritettu, ohjelman pitäisi tuottaa seuraavan kuvan kaltainen näkymä. 11 Kari Laitinen

Harjoitus 4: Lisää ohjelmaan ominaisuus että näytettävää kuvaa ja sen raameja voidaan pienentää tai isontaa Nuoli ylös - ja Nuoli alas -näppäimillä. Katso ohjelmasta KeyboardInputDemoApplet.java kuinka näppäimistöön voidaan reagoida Näppäimistöön reagointia varten tulee tehdä mm. seuraavat operaatiot Ohjelman alussa tulee olla seuraava import -komento, jolla importoidaan kaikki java.awt.event -paketissa olevat luokat import java.awt.event.* ; Luokan alussa tulee lukea implements KeyListener init()-metodissa tulee lukea public void init() {... } addkeylistener( this ) ; Luokasta tulee löytyä kaikki kolme näppäimistöön reagoivaa metodia, vaikka sitten tyhjinä "dummy"-metodeina. 12 Kari Laitinen

Eräs tapa ratkaista tämän tehtävän ongelma on määritellä luokkaan datajäsen double picture_enlargement = 1.0 ; jonka arvoa muutetaan kun nuolinäppäimiä painellaan. paint()-metodissa voidaan sitten haluttu kuvan koko laskea esim. seuraavanlaisilla lauseilla: int desired_picture_width = (int) ( picture_enlargement * picture_width ) ; int desired_picture_height = (int) ( picture_enlargement * picture_height ) ; Harjoitus 5: Jos aikaa riittää ja intoa piisaa, niin lisää ohjelmaan vielä ominaisuus että näytettävää kuvaa voidaan vaihtaa Nuoli oikealle - ja Nuoli vasemmalle -näppäimillä. Tässä voi toimia niin että alussa ladataan näytettävät kuvat Image[] -tyyppiseen taulukkoon, ja pannaan olioviittaaja picture_to_show osoittamaan vuorollaan kuhunkin taulukon kuvaolioon.tämä tarkoittaa että esim. keypressed()-metodissa voidaan siis kirjoittaa picture_to_show = pictures_to_be_shown[ index_of_current_picture ] ; Kun nuolinäppäimiin reagoitaessa pannaan picture_to_show viittaamaan vuorollaan taulukon kuhunkin Image-olioon, vältytään siltä että paint()-metodiin pitäisi tässä osatehtävässä tehdä muutoksia. Tässä osatehtävässä voi kuvataulukon määrittelyn ja luonnin sekä indeksimuuttujan kopioida suoraan ohjelmasta PictureShowApplet.java. 13 Kari Laitinen

HARJOITUKSIA OHJELMALLA VilkkuvaPalloApplet.java Muista että aplettiharjoituksia tehdessä tarvitset aina.html -tiedoston, joka määrittelee sivun jossa apletti toimii. Tehtävät 1, 2 ja 3 voi ratkaista siten että metodeista muutetaan vain ruudun maalauksen suorittavaa paint()-metodia. 1. Nyt pallon värinä on Color.cyan silloin kun sitä näytetään. Muuta ohjelmaa siten että pallon väri muuttuu siten että se on joka toisella kerralla Color.cyan ja joka toisella kerralla Color.magenta silloin kun sitä näytetään. Kun käytetään Color-luokassa määriteltyjä vakiovärejä Color.cyan, Color.magenta, jne., voidaan väriolioita vertailla testaamalla olioviittaajia seuraavaan tapaan if ( pallon_vari == Color.cyan ) {... 2. Muuta ohjelmaa siten että pallo alkaa hiljalleen liikkua alaspäin. Siis kun pallo tulee seuraavan kerran näkyviin, se näkyy muutamaa pikseliä alempana. Tässä pitää myös vartioida että pallon paikan y-koorinaatti ei kasva niin suureksi että pallo katoa kokonaan ruudulta. Tämän tehtävän ratkaisun seurauksena pallo jää vilkkumaan apletin alareunaan sitten kun alareuna on saavutettu. 14 Kari Laitinen

3. Paranna edellisessä kohdassa tehtyä ominaisuutta siten että pallo lähtee nousemaan hiljalleen ylöspäin sitten kun se on saavuttanut apletin alareunan. Kun pallo on saavuttanut apletin yläreunan, se lähtee taas hiljalleen valumaan alaspäin. Tarkoitus on että pallo lopulta "sahaa" jatkuvasti apletin ala- ja yläreunan välissä. Aplettiin kannattaa määritellä seuraava datajäsen jolla pallon liikettä voiaan kontrolloida: boolean pallo_liikkuu_alaspain = true ; Tälle muuttujalle voidaan antaa arvo false sitten kun palloa aletaan siirtämään ylöspäin. 4. Muuta ohjelma sellaiseksi että pallon ylöspäinliikkuminen tapahtuu suunnilleen kaksinkertaisella nopeudella alaspäinliikkumiseen verrattuna. Tämän tehtävän voit ratkaista siten, että erillistä säiettä suoritettavassa run()-metodissa annetaan Thread.sleep()-metodille pienempi nukkumisaika ylöspäinkulkemisen aikana. 5. Muuta ohjelmaa siten että apletin taustaväri muuttuu n. 15 sekunnin välein. Apletin taustaväri voidaan asettaa setbackground()-metodilla. Taustavärit voi tallettaa esim. erilliseen taulukkoon, josta otetaan aina uusi väri käyttöön silloin kun edellistä taustaväriä on käytetty jo mainitut 15 sekuntia. 15 sekunnin kulumisen voi mitata esim. System.currentTimeMillis()-metodin avulla. Kyseinen metodi palauttaa millisekunnit jotka ovat kuluneet vuoden 1970 alusta saakka. Ohjelmaan voi määritellä esim. seuraavat uudet datajäsenet: 15 Kari Laitinen

long taustavarin_asetusaika ; Color[] taustavaritaulukko = new Color[ 4 ] ; int taustavarin_indeksi = 0 ; init()-metodissa voidaan kiinnittää taustaväritaulukkoon värioliot ja asettaa ensimmäinen taustaväri käyttöön seuraavalla tavalla: taustavaritaulukko[ 0 ] = Color.white ; taustavaritaulukko[ 1 ] = Color.lightGray ; taustavaritaulukko[ 2 ] = Color.gray ; taustavaritaulukko[ 3 ] = Color.black ; getcontentpane().setbackground( taustavaritaulukko[ taustavarin_indeksi ]); taustavarin_asetusaika = System.currentTimeMillis() ; Ajan kulumista voidaan seurata esim. run()-metodissa ja asettaa uusi taustaväri käyttöön kun 15 sekuntia edellisestä värin asetuksesta on kulunut. 15 sekunnin kuluminen voidaan havaita esim. seuraavanlaisilla lauseilla: long nykyinen_aika = System.currentTimeMillis() ; if ( nykyinen_aika - taustavarin_asetusaika >= 15000 ) {... 16 Kari Laitinen

HARJOITUKSIA OHJELMALLA MatoPanelApplet.java Kopioi työhakemistoosi MatoPanelApplet.java sekä MatoPanel.html Harjoitus 1 Muuta ohjelmaa, siis käytännössä metodia run(), siten että mato ei "hyppää" takaisin oikeasta reunasta vasempaan reunaan, vaan kulkee tuonkin matkan oikeaoppisesti "luikertelemalla" eli venyen ja supistuen. Tässä tehtävässä kannattaa kopioida oikeallepäin luikertelun suorittava while-silmukka ja tehdä siitä vasemmallepäin luikertelun suorittava silmukka. run() -metodiin tulee siis "ikuisen" while-silmukan sisälle peräkkäin kaksi while-silmukkaa joiden kummankin sisällä on kaksi for-silmukkaa. Vasemmallepäin luikertelun suorittava while-silmukan sisällä olevat for-silmukat on muutettava siten että mato jatkuu vasemmallepäin ja lyhenee oikelta. forsilmukoissa olevia laskurimuuttujia ei tarvitse muuttaa. Harjoitus 2 Lisää luokkaan datajäsenet, esim. int edestakaisten_matkojen_maara = 0 ; int ruudun_maalauslaskuri = 0 ; joiden avulla lasketaan kuinka monta kertaa mato käy ruudun oikeassa reunassa,ja kuinka monta kertaa paintcomponent() -metodia kutsutaan. Näiden muuttujien arvot voi tulostaa esim. ruudun vasempaan yläreunaan. 17 Kari Laitinen

Harjoitus 3 Katso mallia ohjelmasta KeyboardInputDemoApplet.java ja lisää matoaplettiin ominaisuus että madon liikkumisnopeutta voi säätää Arrow Up ja Arrow Down näppäimillä. Tämän ominaisuuden voi toteuttaa esimerkiksi siten että määrittelee datajäsenen int madon_hidastuskerroin = 50 ; joka saa suuremman arvon kun painetaan Arrow Down -näppäintä ja joka pienenee kun Arrow Up näppäintä painetaan. Kun tämmöinen datajäsen on käytössä, erilaisia hitauksia saa aikaan esim. kutsuilla lepuuta_tata_saietta( madon_hidastuskerroin ) ; lepuuta_tata_saietta( 5 * madon_hidastuskerroin ) ; Lisäksi täytyy tehdä: Muuta koodiin implements Runnable, KeyListener Lisää MatoPanel-luokan konstruktoriin kutsu public MatoPanel(... {... } addkeylistener( this ) ; 18 Kari Laitinen

Lisää kaikki metodit näppäimiin reagointiin, ja muista myös lisätä tarpeellinen import - komento, jolla importoidaan kaikki java.awt.event -paketissa olevat luokat. Tässä tehtävässä on hyvä myös käyttää if-rakennetta jolla estetään madon hidastuskertoimen meneminen nollaksi tai negatiiviseksi. Hidastuskertoimen muuttaminen kannattaa laittaa keypressed()-metodiin. (keytyped()-tapahtumaa ei synny nuolinäppäimillä.) Näppäimistöön reagoivia ohjelmia tehtäessä voi joskus joutua klikkaamaan apletin ikkunaa hiirellä ennenkuin näppäimistön luku alkaa toimia. Harjoitus 4: Lisää ominaisuus että madon väri saadaan siniseksi näppäintä S painamalla, punaiseksi näppäintä P painamalla, mustaksi näppäintä M painamalla, ja vihreäksi näppäintä V painamalla. Harjoitus 5: Standardiluokan Math staattisella metodilla Math.random() saadaan aikaan satunnaislukuja. Lisää ohjelmaan ominaisuus että madolle annetaan satunnainen väri kun painetaan näppäintä R. Color-luokassa on konstruktorit joiden avulla väri voidaan määrittää "numeroina". Math.random()-metodia on käytetty mm. Matematiikkaa.java -ohjelmassa. Kyseinen ohjelma löytyy kansiosta jossa on esimerkkejä olio-ohjelmoinnin perusteisiin liittyen. 19 Kari Laitinen

Harjoitus 6: Ota käyttöön PacmanApplet.java-ohjelmassa käytetty "Pacman" ja pistä se suuta aukovana seuraamaan matoa. Pacmanin voi pistää madon perään kun lisää/vähentää sopivan arvon madon x-koordinaatista. Tässä tehtävässä saattaa tarvita datajäsentä boolean mato_liikkuu_oikealle = true ; jonka arvo muuttuu kun madon liikkumissuunta vaihtuu. Pacmanin suun "tahdistuksen" voi laittaa metodin lepuuta_tata_saietta() sisään. PacmanApplet.java löytyy joko www.naturalprogramming.com/javagui/-hakemistosta tai tunnilla annettavasta hakemistosta. 20 Kari Laitinen

HARJOITUKSIA OHJELMALLA MouseDemoApplet.java MouseDemoApplet.java on ohjelma jossa näytetään kuinka Java-sovellus voi reagoida hiiren nappien painamisiin ja hiiren liikkeisiin. Ohjelma on rakennettu siten että kaikki toiminnallisuus on ohjelmoitu luokkaan nimeltä MouseDemoPanel, ja apletin sisään on sitten pantu tämmöinen MouseDemoPanel-olio. Tutki ensin ohjelmaa ja tee sitten seuraavia harjoituksia. Harjoitus 1: Poista näytön sisällön "maalaavasta" metodista paintcomponent() sen nykyiset toiminnot ja tee metodista sellainen että se tulostaa keskelle apletin aluetta tekstin "Et ole klikannut." Tässä kannattaa menetellä, seuraavaa osatehtävää silmälläpitäen, siten että teet luokkaan datajäsenen String text_to_show = "Klikkaa!" ; Ja tulostat tämän stringin arvon paintcomponent()-metodissa. Ohjelmasta DrawingDemoApplet.java näet kuinka stringi piirretään näytölle ja kuinka apletin alueen koko saadaan selville. Alussa stringi kannattaa tulostaa (piirtää) oletusfontilla. Kun saat tekstin näkyviin, voit tulostaa sen suurehkolla fontilla. Ohjelmasta EarthAndMoonApplet.java näet kuinka erilaisia fontteja saadaan käyttöön. Voit määritellä fontin datajäseneksi esim. seuraavasti Font font_for_text = new Font( "Serif", Font.BOLD, 24 ) ; 21 Kari Laitinen

Harjoitus 2: Muuta ohjelma sellaiseksi että hiirellä apletin aluetta klikattaessa näytettävä teksti muuttuu. Tekstiksi pitää tulla "Koillinen" silloin kun klikataan sitä osaa apletin aluetta joka on keskipisteestä katsoen koillisessa, eli alueen pisteet ovat ovat apletin alueen keskipisteestä katsottuna x-koordinaatiltaan suurempia ja y-koordinaatiltaan pienempiä kuin keskipiste. Tekstiksi pitää tulla vastaavasti "Kaakko", "Lounas" tai "Luode" silloin kun klikkaus osuu apletin keskipisteestä katsoen näihin (väli-)ilmansuuntiin. Tässä tehtävässä joudut siis vertaamaan klikatun pisteen koordinaatteja apletin keskipisteen koordinaatteihin. Tämän vertailun voit tehdä mousepressed()-metodissa, josta voit poistaa siellä olevan vanhan ohjelmakoodin. (Tietysti voi käyttää myös mouseclicked()-metodia.) Voit muuttaa näytettävän tekstin (text_to_show) hiireen reagoivassa metodissa. paintcomponent()-metodia ei tarvitse tässä tehtävässä muuttaa. Harjoitus 3: Paranna ohjelman toiminnan näyttävyyttä ("käyttäjäkokemusta") siten että seuraavan kuvan tapaan keskelle tulostuva teksti piirretään laatikon sisään, ja lisäksi viimeksi klikattu ikkunaneljännes väritetään eri värillä. Voit paintcomponent()-metodissa tutkia mikä on näytettävä teksti ja sen mukaisesti maalata neljänneksen alueesta toisella värillä. Stringejä vertailtaessa tulee käyttää equals()-metodia seuraavaan tapaan: if ( text_to_show.equals( "North-East" ) ) 22 Kari Laitinen

Jotta saat tekstin ympärille oikean kokoisen laatikon, joudut ottamaan selville kuinka suuri kyseinen teksti on käytetyllä fontilla kirjoitettuna. Tämän saa selville käyttämällä FontMetrics-luokkaa piirtometodissa seuraavaan tapaan: graphics.setfont( font_for_text ) ; FontMetrics font_metrics = getfontmetrics( font_for_text ) ; int text_width = font_metrics.stringwidth( text_to_show ) ; int text_height = font_metrics.getascent() + font_metrics.getdescent() ; Kun nämä muutokset on ohjelmaan tehty, sen pitäisi tuottaa seuraavan kaltainen näkymä sen jälkeen kuo koilliseen (North-East) on klikattu: 23 Kari Laitinen

Harjoitus 4: Rajapinnan MouseWheelListener ja luokan MouseWheelEvent avulla pystyt lukemaan hiiren rullan liikkeitä. Muuta ohjelma sellaiseksi että keskellä olevan tekstin fonttia voidaan hiiren rullan avulla suurentaa ja pienentää. Font-luokassa on metodi getsize() jolla saadaan selville fontin nykyinen koko. Lisäksi siellä on metodi derivefont() joka palauttaa erikokoisen fontin silloin kun sille annetaan floattyyppinen parametri. Tässä tehtävässä voidaan fontin koko muuttaa mousewheelmoved()-metodissa. paintcomponen()-metodia ei tarvitse muuttaa jos siellä on fontin koon laskenta tehty oikein edellisessä tehtävässä. Harjoitus 5: Muuta ohjelma sellaiseksi että se voidaan resetoida silloin kun painetaan hiiren oikeaa nappia. Resetointi tarkoittaa että näyttöön ilmestyy siellä alussa ollut teksti ja fontiksi tulee alussa käytetty fontti. 24 Kari Laitinen

HARJOITUKSIA OHJELMALLA DrawingSuorakaiteitaApplet.java DrawingSuorakaiteitaApplet.java, joka löytyy suomenkielisten GUI-ohjelmien kansiosta, on ohjelmasta DrawingLinesApplet.java muunnettu versio. Ohjelmaa on muutettu siten että se piirtää hiiren liikkeen määrittämiä suorakaiteita viivojen sijasta. Ohjelma osaa piirtää suorakaiteen "oikein" riippumatta siitä mikä on hiiren liikkumissuunta. Mahdolliset hiiren liikkumissuunnat ja syntyvät suorakaiteet on esitetty alla. Ohjelmassa on metodi nimeltä piirra_suorakaide() joka suorittaa suorakaiteen piirtämisen. Tutki em. metodin toimintaa ja tee sitten seuraavat harjoitukset. 25 Kari Laitinen

Harjoitus 1 Pistä suorakaiteen sisään piirtymään jokin valokuva (.jpg tai.gif tiedosto). Katso mallia ohjelmasta SinglePictureApplet.java. Kuvan piirtämistoiminnon voi laittaa piirra_suorakaide()-metodin sisään. Kun kuva piirretään ennen suorakaidetta, suorakaiteesta tulee kuvalle raamit. Tarkoitus on että tässä käytetään sellaista drawimage()-metodia joka piirtää kuvan samankokoisena kuin suorakaidekin piirretään. Harjoitus 2 Kuten init() -metodista voit nähdä, kutsulla getcontentpane().setbackground(... ) voi asettaa apletin taustavärin. Tee "tyhjille" metodeille mouseentered() ja mouseexited() toiminnot, joiden avulla taustaväri muuttuu keltaiseksi hiiren saapuessa apletin päälle, ja takaisin valkoiseksi hiiren poistuessa apletista. Ruutu on ehkä uudelleenmaalattava jotta asetettu uusi taustaväri tulee käyttöön. 26 Kari Laitinen

Harjoitus 3 Lisää ohjelmaan ominaisuus että jos hiirtä näpäytetään Alt-nappulan ollessa alhaalla, ruudulle piirtyneet suorakaiteet ja kuvat pyyhkiytyvät pois. Luokkaan kannattaa jo seuraavaakin osatehtävää silmällä pitäen määritellä datajäsen boolean piirto_operaatio_kaynnissa = false ; Tämä muuttuja voidaan asettaa mousepressed()-metodissa arvoon true silloin kun Altnappula ei ole alhaalla ja taulukkoon mahtuu pisteiden koordinaatteja. Tällöin voidaan mousedragged()- ja mousereleased()-metodeissa tehdä piirtämiseen liittyviä asioita vain silloin kun em. muuttujalla on arvo true. Muuttuja pitää muistaa asettaa arvoon false silloin kun piirto-operaatio lopetetaan. "Poispyyhintä" voidaan suorittaa mousepressed() metodissa silloin kun Alt-nappula on alhaalla. "Poispyyhintä" saadaan aikaiseksi kun suorakaiteita laskeva muuttuja merkataan nollaksi ja ruutu maalataan uudestaan. MouseEvent -luokkaan on periytynyt metodi isaltdown() jolla Alt-nappulan tila voidaan tutkia. 27 Kari Laitinen

Harjoitus 4 Lisää ohjelmaan viimeisen suorakaiteen ja kuvan poispyyhintäominaisuus joka toimii siten että jos hiirtä klikattaessa on käytössä jokin muu hiiren näppäin kuin vasen hiiren nappäin, niin viimeksi piirretty suorakaide ja sen sisältämä kuva "pyyhkiytyy" pois. Ohjelmasta HiirenKuunteluApplet.java näet kuinka käytetty hiiren näppäin (nappi) saadaan selville. Tämä tehtävä voidaan ratkaista helposti mousepressed()-metodissa jos edellinen osatehtävä on tehty mainittua boolean-muuttujaa käyttäen. Harjoitus 5 Ota mallia ohjelmasta MatoOffscreenApplet.java ja toteuta tässä tekemääsi aplettiin ns. tuplapuskurointi jolla estetään ruudun välkkymistä. update()-metodia ei tuplapuskuroinnin toteutuksessa tarvita, mutta paint()-metodista on poistettava kutsu yläluokan paint()- metodiin. Tarkoitus on että kaikki ruudulle tuleva tavara piirretään ensin "ruudun kuvaan" ja sitten tuo kuva piirretään oikealle ruudulle. Harjoituksessa 2 tehty ominaisuus lakkaa toimimasta kun taustaväri peittyy ruudun täyttävän kuvan alle. Mieti mitenkä saat kyseisen ominaisuuden käyttöön myös ruudun kuvaa käytettäessä. 28 Kari Laitinen

HARJOITUKSIA OHJELMALLA MovingBallApplet.java Harjoitus 1: Lisää aplettiin uusia painonappeja joiden avulla pallon halkaisijaa voidaan kasvattaa ja pienentää. Nykyisellään pallon halkaisija on vakio, 100 pikseliä. Tarvitaan kaksi uutta JButton oliota. Lisää ohjelmaan ensin nämä oliot ja tarkista että ne ilmestyvät ruudulle. Vasta tämän jälkeen nappuloihin kannattaa lisätä toimintaa. Luokkaan tarvitaan datajäseneksi pallon kokoa kuvaava muuttuja jonka arvon tulee muuttua uusien painonappien avulla. Muuttuja voi olla esim. Harjoitus 2: int pallon_halkaisija = 100 ; Lisää ohjelmaan ominaisuus että pallon kokoa voi säätää myös ns. vierityspalkilla joka on luokan JScrollBar olio. Katso mallia ohjelmasta SuorakaideApplet.java ja Java API dokumentaatiosta. (Huomaa että applet_width- ja applet_height-muuttujille on saatava "hyvät" arvot ennenkuin niitä käytetään JScrollBar-olioiden luonnissa.) Harjoitus 3: Muuta ohjelma sellaiseksi että pallon ei sallita menevän apletin alueen ulkopuolelle. Tutki JButton-luokan dokumentaatiota ja ota selville kuinka painonappi deaktivoidaan silloin kun pallo on saavuttanut apletin alueen reunan. Painonappi tulee saattaa takaisin aktiiviseksi sitten kun palloa on liikutettu takaisin apletin keskikohtaa päin. 29 Kari Laitinen

Harjoitus 4: Muuta pallon liikuttamiseen käytettävät painonapit sellaisiksi että ne rakennetaan kuvien avulla. Tähän voi hyödyntää ImageIcon-luokkaa. ImageIcon-olio saadaan luotua painonappiin seuraavalla tavalla: Image left_button_basic_image = getimage( getcodebase(), "arrow_left_light.gif" ) ; left_button = new JButton( new ImageIcon( left_button_basic_image ) ) ; Yllä olevassa esimerkissä luodaan ensin Image-olio jonka avulla tehdään sitten ImageIconolio. Näin on hyvä menetellä erityisesti apletteja tehtäessä kun on varauduttava siithen että kuva varmasti latatutuu palvelimelta. Java-applikaatioita tehtäessä voidaan ImageIcon luoda antamalla konstruktorille parametrina kuvatiedoston nimi. Kuvatiedoston tulee tässä tapauksessa olla samassa kansiossa kuin Java-ohjelman.class-tiedosto. Liikuttelunapeissa tarvittavia nuolten kuvia löydät esim. kansiosta http://www.oamk.fi/~karil/images/ Harjoitus 5: Tutkimalla JButton-luokan tai tarkemmin sanoen sen yläluokan AbstractButton dokumentaatiota saat selville että painonappiin voidaan laittaa myös ns. "roll over icon" joka ilmestyy painonappiin silloin kun hiiri viedään painonapin päälle. Samoin voidaan nappiin laittaa "pressed icon" joka aktivoituu kun nappia painetaan. Laita ainakin yhteen painonappiin tällaiset ikonit. Em. kansiosta löytyy tähän tarkoitukseen erilaisia kuvia ainakin left-nappia varten. 30 Kari Laitinen

Harjoitus 6: Ohjelmasta saa näyttävämmän jos myös näytettävä pallo on tehdy kuvan avulla. Osoitteesta http://www.oamk.fi/~karil/images/ löydät ainakin kolme käyttökelpoista pallon kuvaa jotka ovat sellaisia että pallojen ympäristö on tehty kuvaan läpinäkyväksi. Nämä kuvat voi ottaa käyttöön seuraavanlaisilla lauseilla: jalkapallon_kuva = getimage( getcodebase(), "soccer_ball_1_round.png" ) ; koripallon_kuva = getimage( getcodebase(), "basketball_round.gif" ) ; kummallisen_pallon_kuva = getimage( getcodebase(), "weird_ball.png" ) ; Itse asiassa pallojenkin kuvista kannattaa tehdä ImageIcon-olioita sen tähden että sillä tempulla saa varmistettua että kuvat varmasti latautuvat heti aplettiin. Kuvan voi piirtää seuraavanlaisella lauseella: graphics.drawimage( current_ball_image, ball_center_point_x - pallon_halkaisija / 2, ball_center_point_y - pallon_halkaisija / 2, pallon_halkaisija, pallon_halkaisija, null) ; 31 Kari Laitinen

Ohjelmasta saa vieläkin näyttävämmän jos eri palloille panee erilaisen taustavärin. itemstatechanged()-metodissa voi siten toimia seuraavalla tavalla: public void itemstatechanged( ItemEvent menu_selection ) { String selected_ball = (String) menu_selection.getitem() ; if ( selected_ball.equals( "koripallo" ) ) { current_ball_image = koripallon_kuva ; getcontentpane().setbackground( Color.yellow ) ; } else if... Kun pallo on kuvana, ohjelman ulkoasu voi näyttää esim. seuraavanlaiselta: 32 Kari Laitinen

33 Kari Laitinen

HARJOITUKSIA OHJELMALLA CurtainsApplet.java Harjoitus 1: Näissä harjoituksissa on tarkoitus päätyä siihen että ohjelman verhoista tehdään automaattiset siten että ne liikkuvat napin painalluksella animoidusti. Animaation aikaansaamiseksi täytyy käyttää säikeitä. Ennen säikeen tekoon ryhtymistä kannattaa kuitenkin ohjelma muuttaa sellaiseksi että siihen tulee napit verhojen säätöön. Poista siis ohjelmasta JSlider-säätimet ja pane tilalle painonapit (JButton-oliot) joiden avulla verhot voidaan joko sulkea tai avata. Painonappien käyttöön liittyen voit katsoa mallia MovingBallApplet.java -ohjelmasta. Seuraavat rivit käyvät datakenttien määrittelyksi CurtainsPanel-luokkaan: JButton verhojen_avausnappi = new JButton( "Open" ) ; JButton verhojen_sulkemisnappi = new JButton( "Close" ) ; static final int VERHON_LEVEYS_TAYSIN_KIINNI = WINDOW_WIDTH / 2 + 8 ; static final int VERHON_LEVEYS_TAYSIN_AUKI = 10 ; int verhon_leveys = VERHON_LEVEYS_TAYSIN_KIINNI ; Ohjelma voidaan tehdä siten että verhon leveyttä muutetaan painonappien avulla ja piirtämisessä otetaan aina uusi verhon leveys huomioon. 34 Kari Laitinen

Harjoitus 2: Muuta ohjelma sellaiseksi että verhojen avausnapilla verhot avautuvat hiljalleen, ja verhojen sulkunapilla ne menevät hiljalleen kiinni. Tämän aikaansaamiseksi tarvitset säikeen joka hiljalleen muuttaa verhon leveyttä ja suorittaa näytön uudelleenpäivitystä. Säikeen rakentamiseksi seuraavat datajäsenet voivat olla hyödyllisiä: static final int VERHOT_TAYSIN_AUKI = 0 ; static final int VERHOT_SULKEUTUMASSA = 1 ; static final int VERHOT_AVAUTUMASSA = 2 ; static final int VERHOT_TAYSIN_KIINNI = 3 ; static final int VERHOT_OSITTAIN_AUKI = 4 ; int verhojen_tila = VERHOT_TAYSIN_KIINNI ; Thread saie_verhojen_liikutteluun ; Tämäntyyppisessä ohjelmassa on verhoilla monta tilaa joita yllä määritellyt tilamuuttujan arvot kuvaavat. Voit katsoa tämän ongelman ratkaisemiseen mallia ohjelmasta AurinkoApplet.java joka löytyy suomenkielisten GUI-ohjelmien kansiosta. Tämä verhojen leveyden säätöongelma on itse asiassa helpompi kuin tuo AurinkoApplet.javan auringonliikutteluongelma. 35 Kari Laitinen

Harjoitus 3: Säikeitä käytettäessä on vaarana että ohjelmaan saadaan aikaiseksi hyvin kummallisia ja vaikeasti löydettäviä virheitä. Voi esimerkiksi jäädä useita säikeitä yhtäaikaisesti toimintaan. Verhojen liikuttelussa voi syntyä ongelmia jos painetaan jotain nappia silloin kun animaatio on kesken. Tee niin että ohjelman painonapit deaktivoidaan setenabled()-metodilla siksi ajaksi kun animaatio on käynnissä. Tällä voidaan estää mahdollisia ongelmia. Harjoitus 4: Lisää ohjelmaan Stop-nappi jolla verhojen liike voidaan pysäyttää siinä tapauksessa kun ne ovat joko sulkeutumassa tai avautumassa. Stop-nappi pitää sitten jättä deaktivoimatta siinä tapauksessa kun animaatio aloitetaan. Stopnapin tulee olla deaktiivinen silloin kun avaamis- ja sulkemisnapit ovat aktiivisia. Verhojen pysäytyksen jälkeen verhojen tilaksi tulee VERHOT_OSITTAIN_AUKI. Tuosta tilasta pitäisi päästä taas joko verhojen avaamiseen tai sulkemiseen kun nappeja käytetään. 36 Kari Laitinen

Harjoitus 5: Lisää ikkunaan verhojen taakse sälekaihtimet. Ne saat aikaiseksi piirtämällä silmukalla joukon vaakasuoria matalia suorakaiteita (säleitä) ennen varsinaisten verhojen piirtämistä. Yleensähän sälekaihtimet ovat vaaleanharmaita väriltään. Sälekaihtimet ovat englanniksi Blinds tai Venetian Blinds. Lisää sälekaihdinten säätöön Blinds-painonappi jolla sälekaihtimet saa enemmän tai vähemmän kaihtavaksi. Tämä tarkoittaa säleen korkeuden säätämistä painonapin avulla. Ohjelmassa voit käyttää datakenttää int saleen_korkeus = 1 ; jonka arvo muuttuu Blinds-napin painamisen jälkeen esim seuraavasti: saleen_korkeus = saleen_korkeus + 4 ; if ( saleen_korkeus > 16 ) { saleen_korkeus = 1 ; } Sälekaihtimien säleen korkeus voi siis painonapin avulla saada ensin suurempia arvoja ja sitten taas aloittaa alusta. Näin käyttäjä voi etsiä sopivan asennon kun painaa nappia riittävän monta kertaa. Säleiden korkeuden säätöön ei tarvita animaatiota. 37 Kari Laitinen

HARJOITUKSIA OHJELMALLA PalloLiikkuuHiirellaApplet.java Näissä harjoituksissa tulee olla ohjelma Pallo.java samassa kansiossa kuin PalloLiikkuuHiirellaApplet.java. Luokkaan Pallo ei tarvitse kuitenkaan tehdä mitään muutoksia. Harjoitus 1: Muuta ohjelmaa ottamalla neljäs pallo käyttöön. Tässä tulee määritellä aplettiluokkaan neljäs Pallo-tyyppinen olioviittaaja datajäseneksi, sekä lisätä metodeihin toiminnot joilla tämä neljäskin pallo otetaan huomioon. Metodeihin mousereleased() ja mousedragged() ei tässä tarvitse tehdä muutoksia. Neljäs pallo tulee alussa keskimmäisen pallon kohdalle kun se luodaan seuraavanlaisella lauseella: neljas_pallo = new Pallo( apletin_leveys / 2, apletin_korkeus / 2 + 100, Color.cyan ) ; Harjoitus 2: Johda (periytä) luokasta Pallo uusi luokka nimeltä Rengaspallo. Voit kirjoittaa Rengaspalloluokan esim. tiedoston PalloLiikkuuHiirelläApplet.java alkuun import-lauseiden jälkeen kunhan et tee uudesta luokasta public-luokkaa. Tarkoitus on että Rengaspallo-oliot ovat samanlaisia kuin Pallo-oliot sillä poikkeuksella että Rengaspallo-luokan pallo sisältää mustia renkaita seuraavaan tapaan: 38 Kari Laitinen

Piirtoteknisistä syistä tässä esitetyt renkaat eivät ole ihan ympyröitä, mutta Graphics-luokan metodilla drawoval() on kätevä piirtää ihan oikeita ympyröitä.. Rengaspallo-luokkaan tulee kirjoittaa konstruktori ja uusi versio metodista piirra(). Uusia datajäseniä luokkaan ei tarvitse lisätä. Kun konstruktori tehdään seuraavalla tavalla, ei Palloluokassa tarvita oletuskonstruktoria: public Rengaspallo( int annettu_paikka_x, int annettu_paikka_y, Color annettu_vari ) { super( annettu_paikka_x, annettu_paikka_y, annettu_vari ) ; } Metodi piirra() voidaan tehdä seuraavalla tavalla, jossa ensin kutsutaan Pallo-luokan vastaavaa metodia ja vasta sitten piirretään pallon sisään tarvittavat mustat renkaat: 39 Kari Laitinen

public void piirra( Graphics graphics ) { super.piirra( graphics ) ; // Kutsu Pallo-luokan piirra()-metodiin graphics.setcolor( Color.black ) ; int renkaan_halkaisija = pallon_halkaisija ; while ( renkaan_halkaisija > 0 ) { graphics.drawoval( pallon_keskipiste_x - renkaan_halkaisija / 2, pallon_keskipiste_y - renkaan_halkaisija / 2, renkaan_halkaisija, renkaan_halkaisija ) ; } } renkaan_halkaisija = renkaan_halkaisija - 8 ; Kun olet saanut aikaiseksi uuden Rengaspallo-luokan, sinun tulee luonnollisesti ottaa käyttöön aplettiluokassa Rengaspallo-olio, jolla voit testata tekemääsi luokkaa. Rengaspalloolion lisääminen voidaan tehdä samaan tapaan kuin harjoituksessa 1 lisättiin uusi Pallo-olio. 40 Kari Laitinen

Harjoitus 3: Nykyisessä PalloLiikkuuHiirellaAppletissa on se ongelma että viimeisenä liikutettu pallo ei välttämättä jää päälimmäiseksi jos pallot tulevat ruudulle osittain päällekkäin. Ongelma johtuu siitä että paint()-metodissa pallot piirretään aina samassa järjestyksessä. Luonnollisesti olisi ohjelman käyttäjän kannalta loogista että viimeisenä liikutettu pallo on päällimmäisenä. Tässä harjoituksessa tehtäväsi on poistaa tämä ongelma ohjelmasta. Tämä ongelma voidaan poistaa mm. siten että aplettiluokkaan lisätään datajäseneksi taulukko johon myös tarvittavat olioviittaajat talletetaan. Kun taulukkona käytetään java.util -paketissa määriteltyyn ArrayList-luokkaan perustuvaa taulukkoa, on helppo poistaa juuri liikutettua palloa vastaava olio taulukosta ja lisätä se sitten taulukon loppuun, minkä seurauksena viimeisenä liikuteltu pallo piirtyy myös viimeisenä. Tarvittava ArrayList-taulukko voidaan määritellä ja luoda esim. seuraavalla lauseella ArrayList<Pallo> piirrettavat_pallot = new ArrayList<Pallo>() ; ArrayList-taulukkoa määriteltäessä annetaan kulmasulkeissa < > sen luokan nimi, jonka olioita tai jonka alaluokan olioita taulukkoon aiotaan tallettaa. Kaikki olioviittaajat voidaan tallettaa ArrayList-taulukkoon esim. PalloLiikkuuHiirellaPanel -luokan konstruktorin lopussa seuraavaan tapaan: piirrettavat_pallot.add( eka_pallo ) ; piirrettavat_pallot.add( toka_pallo ) ; jne. 41 Kari Laitinen

Kun Pallo- ja Rengaspallo-olioihin viitataan ArrayList-taulukosta, kaikki pallot voidaan tulostaa paintcomponent()-metodissa seuraavanlaisella silmukalla. size()-metodilla saadaan selville montako oliota ArrayList-taulukkoon on talletettu, ja get()-metodilla voidaan lukea tiettyä indeksiarvoa vastaava olio. for ( int pallon_indeksi = 0 ; pallon_indeksi < piirrettavat_pallot.size() ; pallon_indeksi ++ ) { piirrettavat_pallot.get( pallon_indeksi ).piirra( graphics ) ; } Kun sitten halutaan asettaa viimeksi liikuteltu pallo viimeksi piirrettäväksi, se voidaan tehdä mousepressed()-metodissa heti kun on löydetty liikuteltava pallo. mousepressed()-metodissa voidaan liikuteltava pallo poistaa ensin ArrayList-taulukosta seuraavanlaisella lauseella: piirrettavat_pallot.remove( liikuteltava_pallo ) ; Kun liikuteltava_pallo:n viittaama olio lisätään tämän jälkeen add()-metodilla takaisin taulukkoon, se tulee taulukon viimeiseksi ja piirtyy siten viimeisenä. Nämä operaatiot on luonnollisesti suoritettava sen jälkeen kun liikuteltava_pallo on pantu viittaamaan oikeaan liikuteltavaan palloon. 42 Kari Laitinen

Harjoitus 4: Ohjelmassa on vielä sellainen vika että jos palloja on päällekkäin ruudulla ja klikataan päällimmäistä palloa, aina ei välttämättä tartuta päälimmäiseen pallon vaan hiiren kursoriin saattaa tarttua pallo jostain alta. Muuta mousepressed()-metodi sellaiseksi että tartutaan aina päällimmäiseen palloon. Edellisessä kohdassa käytettyä taulukkoa voidaan tässä hyödyntää. Kyseinen taulukko on sellaisessa järjestyksessä että päällimmäisenä olevat pallot ovat taulukon lopussa. Tämän tehtävän ratkaisussa voi käyttää seuraavantapaista ohjelmarakennetta, jossa taulukkoa käydään läpi lopusta alkuun: Huom! Kuvatiedostojen kanssa työskenneltäessä on int pallon_indeksi = piirrettavat_pallot.size() joskus esiintynyt - 1 selittämättömiä ; ohjelman kaatumisia. Jos tämmöistä ilmenee, kokeile jotain toista boolean klikatun_pallon_etsinta_valmis = kuvatiedostoa. false ; Saattaa olla että jotkut kuvatiedostot ovat jotenkin virheellisiä ja ohjelmia kaatavia. while ( klikatun_pallon_etsinta_valmis == false ) { // Tanne pitaisi jotain sopivaa ohjelmakoodia laittaa } if ( pallon_indeksi > 0 ) { pallon_indeksi -- ; } else { klikatun_pallon_etsinta_valmis = true ; } 43 Kari Laitinen

Harjoitus 5: Kun sinulla nyt on olioviittaukset Pallo-olioihin ArrayList-taulukossa, voit helposti tehdä ohjelmasta sellaisen että ruudulla voi olla "äärettömästi" palloja. Muuta mousepressed()- metodi sellaiseksi että hiiren keskimmäisellä napilla ArrayList-taulukon loppuun lisätään uusi Rengaspallo-olio ja oikealla hiiren napilla sinne lisätään tavallinen Pallo-olio. Nämä uudet pallot piirtyvät ruudulle automaattisesti jos edelliset osatehtävät on tehty oikein. Kun kaikki viittaukset pallo-olioihin ovat ArrayList-taulukossa, voit niin halutessasi luopua kokonaan olioviittaajista eka_pallo, toka_pallo, jne. 44 Kari Laitinen

HARJOITUKSIA OHJELMALLA PelikortitApplet.java Harjoitus 1: Muuta Kortti-luokan piirra()-metodia siten että punaisten maiden numerotiedot kirjoitetaan punaisella ja mustien maiden numerotiedot mustalla. Tässä muutos kohdistuu vain Korttiluokan piirra()-metodiin, koska Kortti-olio on sellainen että se tietää itse kuinka se piirtyy ruudulle. Harjoitus 2: Muuta ohjelma sellaiseksi että korttipakka on valmiiksi sekoitettu silloin kun ohjelma käynnistyy. Harjoitus 3: Tee ohjelmasta yksinkertainen pokerikäden parannuspeli siten että rivi_kortteja -taulukosta ja siten myös näytöltä poistetaan klikatut kortit, ja sitten kun painetaan Jaa kortit -nappia niin poistettujen korttien tilalle otetaan taulukon loppuun uudet kortit. Tarkoitus on että pelaaja voi poistaa rivistä kortteja ja ottaa tilalle uusia kunnes hän on saanut aikaiseksi esim. jonkin pokeripelin "käden". ("Yksinäisen" kortin voi tässä jättää käyttämättömäksi. Kortit kannattaa heti alussa kääntää oikeinpäin. ) Korttien poistaminen ArrayList-pohjaisesta taulukosta voi tapahtua lauseella rivi_kortteja.remove( kortin_indeksi ) ; Tässä siis halutaan että Jaa kortit -nappi ei tyhjennä koko korttiriviä, vaan lisää sinne vaan 45 Kari Laitinen

puuttuvan määrän kortteja loppuun. Kun kortteja halutaan lisätä epätäyteen korttiriviin, se voidaan tehdä seuraavanlaisella silmukalla: int kortteja_rivissa = rivi_kortteja.size() ; while ( kortteja_rivissa < 5 ) { Kortti uusi_kortti_riviin = korttipakka.ota_kortti() ; uusi_kortti_riviin.kaanna_kortti() ; rivi_kortteja.add( uusi_kortti_riviin ) ; } kortteja_rivissa ++ ; Korttirivissä olevien korttien paikat näytöllä voidaan asettaa uudelleen seuraavanlaisella silmukalla: for ( int kortin_indeksi = 0 ; kortin_indeksi < rivi_kortteja.size() ; kortin_indeksi ++ ) { Point kortin_paikka = new Point( 40 + ( Kortti.KORTIN_LEVEYS_PIKSELEINA +20 ) * kortin_indeksi, 50 ) ; } rivi_kortteja.get( kortin_indeksi ). aseta_paikka_pikseleina( kortin_paikka ) ; 46 Kari Laitinen

Harjoitus 4: Lisää ohjelmaan ominaisuus että se tutkii ovatko rivi_kortteja-taulukossa olevat kortit samaa maata. Mikäli ne ovat samaa maata, eli kortit muodostavat pokeripelin värin, ohjelma ilmoittaa tästä jotenkin käyttäjälleen. Eräs tapa ilmoittaa että väri on löytynyt on muuttaa apletin taustaväri esim. punaiseksi. Kortti-luokassa on valmiina metodi nimeltä on_samaa_maata_kuin() jolla jotain Kortti-oliota voidaan verrata maan suhteen johonkin toiseen Kortti-olioon. Tässä voi toimia esim. siten että taulukon ensimmäistä korttia verrataan ehtolausekkeessa vuorotellen taulukon muihin kortteihin. Harjoitus 5: Muuta Sekoita pakka -nappi Uusi peli -napiksi. Kun tätä nappia painetaan rivi_kortteja - taulukko tyhjennetään, luodaan uusi korttipakka, sekoitetaan uusi pakka ja asetetaan taustaväri alkuperäiseen arvoonsa. Harjoitus 6: Muuta ohjelma enemmän peliksi siten että liität siihen yksinkertaisen ajanmittaustoiminnon. Eräs tapa ajan mittaukseen on käyttää System.currentTimeMillis()-metodia, joka palauttaa kutsuhetkiset koneen kellon millisekunnit. Metodia voidaan käyttää seuraavasti: long nykyinen_aika = System.currentTimeMillis() ; Kun alussa otetaan talteen pelin aloitusaika seuraavasti long aloitusaika = System.currentTimeMillis() ; saadaan kulunut aika millisekunteina selville kun nykyisestä ajasta vähennetään aloitusaika. 47 Kari Laitinen

Kulunut aika voidaan aina päivittää ja näyttää sen jälkeen kun kortteja käännellään tai uusia kortteja jaetaan. Lopussa, kun väri on löytynyt, näytetään lopullinen kulunut aika. Aloitusaikaa voidaan alkaa mitata esimerkiksi silloin kun käyttäjä ensimmäisen kerran painaa Jaa kortit -nappia. Tässä kannattaa käyttää datajäsenenä muuttujaa boolean peli_kaynnissa = false ; jolla kontrolloidaan pelin kulku. Tässä pelissä mahdollisimman pieni aika on hyvä tulos. Aikaan vaikuttaa se kuinka nopeasti pelaaja kääntelee kortteja ja lisäksi se mitenkä kortit sattuvat pakassa olemaan. Mieti mitenkä reaaliaikainen kuluneen ajan näyttö voitaisiin toteuttaa. 48 Kari Laitinen

HARJOITUKSIA OHJELMALLA BouncingBallApplet.java Harjoitus 1: Laita aluksi ohjelmaan toinen pomppiva pallo. Tämän saat aikaan kun laitat BouncingBallPanel-luokkaan datajäsenen ExplodingBouncer toinen_pallo ; ja sitten ko. luokan konstruktorissa luot ExplodingBouncer-olion seuraavaan tapaan toinen_pallo = new ExplodingBouncer( new Point2D.Double( applet_width / 2, applet_height / 2 ), Color.CYAN, bouncing_area) ; Yllä olevalla tavalla tehtynä toisella pallolla on alussa sama paikka kuin vanhalla pallolla. Uusi pallo lähtee kuitenkin lentämään eri suuntaan koska pallon suunta arvotaan satunnaisesti. Jotta saat uuden pallon liikkumaan, tulee run()-metodiin lisätä seuraava kutsu toinen_pallo.move() ; Jotta saat uuden pallon piirtymään, tulee paintcomponent()-metodiin lisätä seuraava kutsu toinen_pallo.draw( graphics2d ) ; 49 Kari Laitinen

Harjoitus 2: Muuta ohjelma sellaiseksi että sen käynnistyessä lähtee 10 palloa pomppimaan näytöllä. Tämä voidaan tehdä loogisessa mielessä samaan tapaan kuin toimittiin edellisen kohdan yhden pallon kanssa. Tässä voi käyttää java.util -paketissa olevaa ArrayList-luokkaa jolla voidaan rakentaa dynaaminen taulukko. Taulukko BouncingBall-olioille voidaan määritellä seuraavasti ArrayList<ExplodingBouncer> pelin_pallot = new ArrayList<ExplodingBouncer>(); ja oliot taulukkoon voidaan tehdä seuraavasti for ( int pallolaskuri = 0 ; pallolaskuri < 10 ; pallolaskuri ++ ) { ExplodingBouncer uusi_pallo = new ExplodingBouncer( new Point2D.Double( applet_width / 2, applet_height / 2 ), Color.MAGENTA, bouncing_area) ; } pelin_pallot.add( uusi_pallo ) ; 50 Kari Laitinen

Taulukossa olevia palloja voidaan liikutella seuraavanlaisella silmukalla for ( ExplodingBouncer liikuteltava_pallo : pelin_pallot ) { liikuteltava_pallo.move() ; } Taulukossa olevat pallot voidaan piirtää seuraavanlaisella silmukalla for ( ExplodingBouncer piirrettava_pallo : pelin_pallot ) { piirrettava_pallo.draw( graphics2d ) ; } Kun olet saanut ArrayList-taulukossa olevat pallot toimimaan, voit poistaa alkuperäisen pallon ja alussa lisäämäsi pallon ohjelmasta. (Voit helposti lisätä palloja ArrayListtaulukkoon jos tuntuu että pelissäsi on liian vähän palloja.) Harjoitus 3: Tee kaikille palloille erilainen pohjaväri. Voit käyttää konstruktorissa seuraavaa taulukkoa, josta otat indeksoimalla pallon värin ennen pallo-olion luontia: Color[] ball_colors = { Color.CYAN, Color.MAGENTA, Color.YELLOW, Color.PINK, Color.WHITE, Color.BLACK, Color.BLUE, Color.ORANGE, Color.RED, Color.GREEN.brighter() } ; Tämän tehtävän teko ei ole edellytys seuraaavan tehtävän tekemiselle. 51 Kari Laitinen

Harjoitus 4: Ohjelmassa käytetyille ExplodingBouncer-olioille on käytössä metodi nimeltä contains_point(), jolla voidaan tutkia onko jokin piste pallon eli pomppijan alueen sisällä. Lisäksi on käytössä metodi explode_ball(), jolla pallo saadaan räjähtämään. Tehtäväsi on tässä lisätä hiiritoiminto mukaan ohjelmaan siten että hiirellä jotakin palloa klikattaessa se räjähtää ja hiljalleen katoaa näytöltä. Tässä siis ohjelmasta tulee eräänlainen pallojentuhoamispeli. Esim. silloin kun hiiren nappi painetaan alas voidaan kysyä jokaiselta ArrayList-taulukossa olevalta pallolta että sattuiko klikattu piste pallon alueelle. Sitten tuhotaan kyseinen pallo jos klikkaus osui sen alueelle. Huomaa, että pallon tuhoamiseen riittää kun kutsutaan ko. pallon suhteen explode_ball()- metodia. ExplodingBouncer-luokassa on jo valmiina automatiikka jolla pallo tuhoutuu hiljalleen sitten kun se on räjäytetty explode_ball()-metodilla. Ohjelman alkuperäisessä versiossa explode_ball()-metodia kutsutaan silloin kun painetaan näppäimistön Esc-näppäintä. 52 Kari Laitinen

Harjoitus 5: Lisää peliin ominaisuus että se käynnistyy vasta kun Space-näppäintä eli välilyöntinäppäintä painetaan. Tämä on aika helppo tehdä kun määrittelee BouncingBallPanel-luokkaan datajäsenen boolean peli_kaynnissa = false ; jolle annetaan arvo true sitten kun Space-näppäintä on painettu. Tarkoitus on että palloja aletaan liikuttelemaan vasta sitten kun yllä mainittu muuttuja on saanut arvon true. Pallot kyllä voidaan piirtää vaikka mainitulla muuttujalla on arvo false. Tällöin ne piirtyvät päällekäin keskelle ohjelman piirtoaluetta. Pallot sitten sinkoutuvat eri suuntiin automaattisesti kun Space-näppäintä on painettu. Harjoitus 6: Tee ohjelmaan ominaisuus että kun kaikki pallot on räjäytetty, siinä tuhotaan ArrayListtaulukosta kaiki tuhoutuneet pallot ja luodaan pallot uudestaan. Ohjelma voi taas tässä tilanteessa jäädä odottamaan Space-näppäimen painallusta. Tässä on ExplodingBouncer-luokkaan tehtävä boolean-tyyppinen metodi is_exploded() joka palauttaa arvon true siinä tapauksessa kun pallon tila on BALL_EXPLODED. Tuon metodin avulla tulee sitten kaikkien pallojen tila tutkia esim. ennen niiden liikuttamista. Jos kaikki pallot ovat räjähtäneet, toimitaan tässä tehtävässä määritellyllä tavalla. Erillinen metodi tarvitaan koska pallo ei ole räjähtänyt heti kun explode_ball()-metodia on kutsuttu. 53 Kari Laitinen

HARJOITUKSIA OHJELMALLA FlagsApplet.java Harjoitus 1: Ohjelma FlagsApplet.java on esimerkki mm. standardiluokan JTabbedPane käytöstä. Kyseisellä luokalla voidaan rakentaa graafinen käyttöliittymä joka koostuu "tabeista" eli välilehdistä. Tutki luokan JTabbedPane dokumentaatiota ja muuta FlagsApplet.java sellaiseksi että sen välilehdet voidaan valita näppäimistön avulla. Tämä pitäisi saada aikaiseksi setmnemonicat()-metodin avulla. Käytä myös settooltiptextat()-metodia jolla välilehdille voidaan asettaa "vinkkiteksti" joka tulee näkyviin kun hiiri viedään välilehden valinnan kohdalle. Harjoitus 2: Lisää ohjelmaan uusi välilehti "Fictitious" johon kuuluvaan FlagPanel-olioon lisätään kuvitteellisten maiden lippuja. Tätä ominaisuutta rakentaessasi voit sinne laittaa aluksi ihan jonkin jo määritellyn lippuolion, mutta suositus on että määrittelet CrossFlag-luokan avulla "AntiFinland" -nimisen maan lipun ja laitat tuon lipun tuohon "Fictitious"-lippujen välilehdelle. "AntiFinland" -lipussa on sininen tausta ja siinä valkoinen risti. "AntiFinland"- lipussa voi risti olla horisontaalisesti toisinpäin verrattuna Suomen lippuun. Tätä harjoitusta tehdessäsi voit myös korjata FlagPanel-luokasta sen ongelman että se ei toimi jos paneeliin ei ole lisätty yhtään lippua. Tämän ongelman syy on se että ArrayListtaulukosta yritetään näyttää aina ensimmäistä lippua, ja jos tuota ensimmäistäkään lippua ei ole niin syntyy ongelmia. Tämä ongelma voidaan ratkaista tutkimalla size()-metodilla FlagPanel-luokan paintcomponent()-metodissa, onko ArrayList-taulukko tyhjä. 54 Kari Laitinen