LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson PROGRAMMERING I SPRÅKET JAVA Innehåll 1. VI BÖRJAR PROGRAMMERA..................................................................................................................................2 INLEDNING......................................................................................................................................................................2 NEDLADDNING OCH INSTALLATION AV JAVA........................................................................................................................2 JAVA MED TEXTPAD........................................................................................................................................................3 JAVADOKUMENTATION......................................................................................................................................................3 FÖRSTA PROGRAMMET I JAVA - UTMATNING.........................................................................................................................4 INMATNING MED STANDARDKLASSER...................................................................................................................................5 String och tecken....................................................................................................................................................5 Heltal och decimaltal..............................................................................................................................................6 AVRUNDNING..................................................................................................................................................................6 HELTALSDIVISION............................................................................................................................................................6 ASCII-KOD...................................................................................................................................................................6 MATEMATISKA FUNKTIONER..............................................................................................................................................7 URVAL OCH LOOPAR........................................................................................................................................................7 FÄLT (ARRAY)................................................................................................................................................................8 2. GRAFISKA METODER.............................................................................................................................................10 FÖNSTER (FRAME).........................................................................................................................................................10 FÄRGER.......................................................................................................................................................................10 LINJE I FÖNSTER............................................................................................................................................................11 TEXT I FÖNSTER............................................................................................................................................................11 INSTANSVARIABLER MED KONSTRUKTOR OCH OBJEKT...........................................................................................................13 INLÄSNING AV VARIABLER...............................................................................................................................................14 3. APPLETS OCH GRAFISKA KOMPONENTER...................................................................................................15 APPLETS......................................................................................................................................................................15 PARAMETRAR I HTML-KODEN.......................................................................................................................................16 GRAFISKA KOMPONENTER...............................................................................................................................................17 Knapp....................................................................................................................................................................17 Textruta.................................................................................................................................................................18 Etikett (label)........................................................................................................................................................19 Egenskaper hos komponenter...............................................................................................................................20 Rullningslist (scrollbar)........................................................................................................................................21 4. MUS- OCH TANGENTHÄNDELSER.....................................................................................................................22 MUSHÄNDELSER............................................................................................................................................................22 OVERRIDE PÅ UPDATE....................................................................................................................................................23 RITA UTAN PAINT..........................................................................................................................................................25 TANGENTHÄNDELSER......................................................................................................................................................25 5. ANIMERING MED TRÅDAR...................................................................................................................................27 TRÅDAR OCH MULTITASKING...........................................................................................................................................27 MULTIPELT ARV OCH GRÄNSSNITT I JAVA..........................................................................................................................27 KLASSEN THREAD OCH GRÄNSSNITTET RUNNABLE..............................................................................................................27 TVÅ TRÅDAR................................................................................................................................................................28 TRÅDAR I EGEN KLASS....................................................................................................................................................29 6. KLASSER I EGNA FILER.........................................................................................................................................32 EGEN KLASSFIL.............................................................................................................................................................32 /home/micko/Skrivbord/java_lektioner.doc 1 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson 1. Vi börjar programmera Inledning Denna kurs i Java-programmering bygger på goda kunskaper i språket C++ och på att begrepp som variabler, urval, loopar, objekt etc. är kända. Kan man C++ är det dock relativt enkelt att lärar sig Java, eftersom Java till härstammar ifrån och till stor del har samma syntax som C++. Språket Java skapades 1991 av den kanadensisk-amerikanske programmeraren James Gosling vid dataföretaget Sun Microsystem och blev allmänt tillgängligt 1995. Ursprungligen var Java tänkt som ett språk för konsumentartiklar (typ tvättmaskiner), men kom i början främst att användas för bla grafiska effekter med s k applets på Internet. Java har emellertid nu slagit igenom stort och i viss mån ersatt traditionella språk som C++. Java har många fördelar: • Syntaxen är i stort sett identisk med C++. Java är därför relativt enkelt att lära sig för den som redan kan C eller C++. • Det är plattformsoberoende, d v s ett program kan köras i olika operativsystem (Windows 2000, Unix etc.) utan att ändras. • Det innehåller grafiska verktyg såsom knappar och textrutor (som VB) även om programmeringen görs i en texteditor. • Det stödjer s k trådar (threads). Exempelvis kan det rita upp en bild samtidigt som det gör en inläsning. • Det kan användas på Internet för att skapa dynamiska funktioner på webbsidor. Detta görs med javaapplets. • Det saknar pekare, vilket innebär att ett program i Java ofta är enklare att förstå än i C++. Java har också några nackdelar: • Det är ett s k interpreterande (d v s översätter kod vid varje exekvering) språk och därför långsammare än t ex C++. Detta kompenseras dock av att dagens datorer är så pass snabba att detta ofta inte är något hinder. • Det är ett innehållsrikt språk med väldigt många färdiga standardklasser (bl a för grafik) som kan vara svåra att få grepp om. Man behöver dock inte lära sig allt på en gång. I denna javakurs berörs främst syntax och begrepp som skiljer sig från C++, som tas upp i kursdokumentet http://hem.passagen.se/anderskristerandersson/data/Cplus_lektioner.doc. Nedladdning och installation av Java En av fördelarna med Java är att utvecklingsmiljön JDK (Java Development Kit, som bl a innehåller kompilatorn) är gratis. Programmet (52 MB) j2sdk-1_4_2_07-windows-i586-p.exe laddas ner från företaget Suns hemsida http://java.sun.com/j2se/1.4.2/download.html till din dator. När programmet installeras skapas mappen c:/ j2sdk1.4.2_07, där programmet packas upp. Javaprogrammen utvecklade med JDK och körs sedan i konsollmiljö, d v s programmen skrivs i en textredigerare typ Anteckningar och de kompileras och exekveras i MS-DOS via Kommandotolken i Tillbehör. I mappen c:/ j2sdk1.4.2_07/bin finns bl a filen javac.exe, som använs för att kompilera javaprogram. Väljer vi att spara våra javaprogram i en annan mapp än mappen bin ovan, vilket är det vanligaste, måste sökvägen anges till bin-mappen så att filen /home/micko/Skrivbord/java_lektioner.doc 2 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson javac.exe hittas. Detta är krångligt. För att slippa ange sökvägen kan vi istället lägga in en sökväg (path) till mappen bin via Kontrollpanelen/System/Avancerat/Miljövariabler. Markera Path i den undre rutan och klicka på knappen Redigera. Skriv där in sökvägen C:\j2sdk1.4.2_07\bin, enligt urklippet intill. Javaprogram kan nu kompileras och köras (exekveras) via kommandotolken. Java med TextPad För att slippa skriva javaprogrammen i Anteckningar och kompilera och exekvera i DOS-miljön skall vi använda oss av editeringsprogrammet TextPad. Programmet (2Mb) laddas ner från http://www.download.com. Installera programmet och öppna det sedan via Start/Alla program. Programmet TextPad är en mer avancerad editor än Anteckningar, bl a görs automatisk indentering och färgning av texten. Dessutom kan javaprogrammen kompileras och köras i TextPad, utan att sökvägen till bin-mappen i Miljövariabel behöver anges (som i förra stycket). Programmet kompileras och körs via menyvalet Tools/Compile Java (Ctrl+1) respektive Tools/Run Java Application (Ctrl+2). Javadokumentation Java är ett stort språk med väldigt många standardklasser och metoder. Detta finns samlat i en dokumentation som kan laddas ner som ett zippat dokument (30 MB) från Suns hemsida http://java.sun.com/j2se/1.4.2/download.html. Uppackat blir dokumen knappt 200 MB stort. Dokumentet finns även uppackat i j:/Anders_A/java/javadokumentation/index.html. /home/micko/Skrivbord/java_lektioner.doc 3 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Första programmet i Java - utmatning Skriv in följande program i TextPad: class test1{ public static void main(String args[]){ System.out.println("Det funkar i textpad!"); System.out.println("Deta är andra raden"); System.out.print("Tredje raden"); System.out.print("Fjärde raden"); } } //Klamrar på samma rad (ej som i C++) //main-metoden börjar //Ger utskrift //println, ny rad efter utskrift //print, ej ny rad efter utskrift //main-metoden slutar Programmets enda klass heter test1, som kan ses som programmets namn. Källkodfilen skall ha samma namn som programmet. Spara därför programmet som test1.java i mappen java, där du i fortsättningen sparar alla dina javaprogram. Filslutet .java anger att det är en källkodfil för ett javaprogram. Kompilera nu programmet till bytekod (andra program kompilerar direkt till maskinkod). Då skapas klassfilen test1.class, som är plattformsoberoende. När klassfilen sedan körs med en javatolk interpreteras den till maskinkod. Ordet public anger att main-metoden (som i C++) är åtkomlig utifrån klassen (programmet) test1, vilket den måste vara för att den skall kunna anropas av av interpretatorn. Ordet static anger att main-metoden är en s k klassmetod (eller statisk metod), d v s en metod som inte hör till ett visst objekt. Parametern String args[] i main-metoden skall alltid vara med för att main-metoden skall kunna anropas med en parameter, vilket dock sällan görs. Följande program illustrerar variabeldeklaration och addition. Observera likheterna med C++: class test3{ public static void main(String args[]){ int a,b=5; double c=3.33; a=7; System.out.println("Summan är " + (a+b) +" och decimaltalet " + c); } } Utelämnas parentesen runt additionen (a+b) i utskriften blir värdet 75. /home/micko/Skrivbord/java_lektioner.doc 4 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Inmatning med standardklasser Som du såg i förra exemplen är utskrift i textfönstret i Java relativt enkelt. Inläsning från tangentbordet är krångligare. Främsta skälet till detta är att Java oftast använder grafiska gränssnitt och därför saknar bra standardklasser för konsollprogrammering. String och tecken Följande program läser in och skriver ut två textsträngar: import java.io.*; //Standardpaketet java.io.* innehåller metoder för in- och utmatning. class test3{ public static void main(String args[]) throws IOException{ //Tar hand om fel i readLine() String fnamn, enamn; //Klassen String används (jämför med C++) BufferedReader in=new BufferedReader(new InputStreamReader(System.in));//krångligt System.out.print("Ange ett förnamn: "); fnamn=in.readLine(); //Förnamnet läses in System.out.print("Ange ett efternamn: "); enamn=in.readLine(); //Efternamnet läses in System.out.println("Du matade in namnet " + fnamn + " " + enamn); } } Vad den krångliga raden som skapar (objekt-) strömmen in för inläsning egentligen innebär bryr vi oss inte om. Enskilda tecken (char) plockas enklast ur en inläst string: System.out.print("Ange en tecken: "); String s=in.readLine(); System.out.println("Du matade in tecknet " + s.charAt(0)); //Ger strängens första tecken String-metoden s.charAt(n) plockar ut n:te tecknet ur strängen s. Följande metoder finns för hantering av strängar, d v s metoder i klassen String: str.length() str.charAt(n) str.substring(n) str.substring(n,m) str.compareTo(str2) str.equals(str2) str.equalsIgnoreCase(str2) str.startsWith(str2) str.startsWith(str2,n) str.endsWith(str2) str.indexOf(c) str.indexOf(c,n) str.lastIndexOf(c) str.lastIndexOf(c,n) str.indexOf(str2) str.indexOf(str2,n) str.lastIndexOf(str2) str.lastIndexOf(str2,n) str.trim() str.replace(c1,c2) str.toUpperCase() str.toLowerCase() String.valueOf(x) /home/micko/Skrivbord/java_lektioner.doc //ger antalet tecken i str //ger tecknet i position n //ger den delsträng som börjar i position n //ger den delsträng som börjar i position n och slutar i m-1 //ger 0 om str = str2 , <0 om str kommer före str2 annars >0 //true om str och str2 är lika, annars false //samma som ovan, men skiljer inte på stora och små bokstäver //true om str inleds med strängen str2, annars false //true om strängen str2 börjar i position n i str, annars false //true om str avslutas med strängen str2, annars false //ger första positionen om tecknet c finns i strängen str, annars -1 //letar från position n efter första platsen för tecknet c //ger sista positionen om tecknet c finns i strängen str //letar från position n efter sista platsen för tecknet c //ger första positionen för delsträngen str2 i str //letar från position n efter första platsen för strängen str2 //ger sista positionen om delsträngen str2 finns i strängen str //letar från position n efter sista platsen för delsträngen str2 //returnerar str utan inledande och avslutande blanktecken //ersätter alla tecken c1 med tecken c2 (å, ä och ö går ej att ersätta) //ändrar till enbart stora bokstäver //ändrar till enbart små bokstäver //omvandlar x till en sträng (x är enkel taltyp: int , double osv) 5 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Heltal och decimaltal All inläsning görs som strängar och omvandlas sedan till t ex integer eller double. Följande program läser in och skriver ut hel- och decimaltal: import java.io.*; class test3{ public static void main(String args[]) throws IOException{ int i; double d; String s; BufferedReader in=new BufferedReader(new InputStreamReader(System.in)); System.out.print("Ange ett heltal: "); s=in.readLine(); i=Integer.parseInt(s); //Omvandlar sträng till heltal System.out.println("Du matade in heltalet " + i); System.out.print("Ange ett decimaltal: "); s=in.readLine(); d=Double.parseDouble(s); //Omvandlar sträng till decimaltal System.out.println("Du matade in decimaltalet " + d); } } Metoderna parseInt(s) och parseDouble(s) tillhör klasserna Integer respektive Double. Inläsning till heltal direkt kan göras med följande sats: int antal=Integer.parseInt(in.readLine()); Avrundning Även avrundning är ganska krånkligt i Java. Följande program avrundar till tre decimaler: import java.io.*; import java.text.*; //Klassen NumberFormat finns i detta paket class test3{ public static void main(String args[]) throws IOException{ double d=3.823456; NumberFormat r = NumberFormat.getInstance(); //Instans av redigerare r r.setMaximumFractionDigits(4); //Formaterar utrskrift till högst 4 decimaler System.out.println("Med fyra decimaler: " + r.format(d) ); //Omvandlar decimaltalet d till //en sträng med 4 decimaler } } Heltalsdivision Fungerar på samma sätt som i C++, d v s är båda termerna heltal blir kvoten ett heltal. Problemet löses med casting, d v s omtypning. ASCII-kod ASCII-koden erhålls i Java liksom i C++ genom omtypning av ett tecken: String s="Anders"; System.out.println("ASCII-koden för femte tecknet: " + (int)s.charAt(4)); Tecknet för motsvarande ASCII-kod fås på omvänt sätt: int i=232; System.out.println("Tecknet är: " + (char)i); /home/micko/Skrivbord/java_lektioner.doc 6 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Matematiska funktioner Klassen Math i Java har några metoder (funktioner) som C++ saknar. Följande program visar vilka: import java.io.*; import java.lang.*; //Innehåller klassen Math. Paketet behöver inte importeras, finns alltid med. class test3{ public static void main(String args[]) throws IOException{ System.out.println(Math.PI); //Ger pi med 15 decimaler System.out.println(Math.pow(5,2)); //25.0 System.out.println(Math.sqrt(49)); //7.0 System.out.println(Math.random()); //Slumptal mellan 0-1. ’Blandas’ automatiskt. System.out.println(Math.max(5,8)); //8 System.out.println(Math.min(5,8)); //5 System.out.println(Math.round(5.5)); //6 } } Observera att klassnamnet Math måste föregå metodanropet. Nedan följer en sammanställning av de matematiska metoderna: Math.abs(a) Math.max(a,b) Math.min(a,b) Math.PI Math.E Math.exp(x) Math.log(x) Math.sqrt(x) Math.ceil(x) Math.floor(x) Math.pow(x,y) Math.round(x) Math.random() Math.sin(x) Math.cos(x) Math.tan(x) Math.asin(x) Math.acos(x) Math.atan(x) //absolutvärdet eller beloppet av talet a //ger det största av talen a och b //ger det minsta av talen a och b //talet π //talet e = 2,7… //ger ex //ger naturliga logaritmen av x //ger kvadratroten av x //rundar av uppåt till heltal //rundar av nedåt till heltal //ger xy //avrundar till heltal av typ long //ger slumptal mellan 0 och 1 //x anges i enheten radianer //arcsin(x), motsvarar miniräknarens sin-1. Returnerar ett värde i radianer. Urval och loopar Urval med if och case, samt looparna for och while har samma syntax i Java som i C++. /home/micko/Skrivbord/java_lektioner.doc 7 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Fält (array) I Java är fält dynamiska så till vida att storleken kan anges vid exekveringen (jämför med pekare i C++). Dessutom innehållet klassen Arrays metoder för bl a sortering, sökning och jämförelse av fält. Följande program illustrerar hur en vektor fylls med hela slumptal mellan , sorteras i stigande ordning, samt slutligen skrivs ut igen: import java.io.*; import java.lang.Math; import java.util.Arrays; //Importerar klassen Arrays för att kunna sortera fältet nedan class test3{ public static void main(String args[]) throws IOException{ int [] a=new int[10]; //Deklarerar fältet med new (påminner om pekare i C++) for (int i=0;i<10;i++) a[i]=(int)(Math.random()*5)+1; //Fyller fältet med slumptal mellan 1 och 5 Arrays.sort(a); //Sorterar fältet i stigande ordning for (int i=0;i<10;i++) System.out.println(a[i]); } } Sortering av strängar görs på liknande sätt. Sorteringen fungerar dock endast om hela det deklarerade fältet är fyllt. Deklarationen av fältet görs därför efter inläsningen av fältets storlek: System.out.print("Ange hur många namn som skall matas in: "); int antal=Integer.parseInt(in.readLine()); //Omvandling till heltal görs direkt String [] a=new String[antal]; Klassen Arrays innehåller bl a följande användbara metoder: a.length Arrays.equals(a,b) Arrays.fill(a,b) Arrays.fill(a,m,n,b) Arrays.sort(a) Arrays.sort(a,m,n) binarySearch(a,b) //Ger antalet komponenter i a (tillhör ej klassen Arrays) //Returnerar true om fälten a och b är lika (komponenter och antal) //Ger alla komponenterna i fältet a värdet b //Returnerar komponenterna nr m till n-1 I fältet a värdet b //Sorterar komponenterna i a i stigande ordning //Sorterar komponenterna nr m till n-1 i a i stigande ordning //Söker efter variabeln b i fältet a. Returnerar b:s index om den finns, annars -1 Övning 1.1: Skriv ett program som skriver ut följande textsträng på skärmen: Detta är kul. Detta är kul. Detta är kul. Övning 1.2: Skriv ett program som läser in ett namn och sedan skriver ut det på skärmen på tre rader: Vad heter du: Anders Andersson Var bor du? Skoghall Du heter Anders Andersson och bor i Skoghall Du heter Anders Andersson och bor i Skoghall Du heter Anders Andersson och bor i Skoghall Övning 1.3: Skriv ett program som beräknar resten vid division mellan två heltal. Programmet skall ha följande utskrift: Ange taljare: 16 Ange namnare: 6 Rest vid division: 4 Heltalsdivision: 2 Kvot med alla decimaler: 2.6666666666666665 /home/micko/Skrivbord/java_lektioner.doc 8 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Kvot med tre decimaler: 2.667 Övning1.4: Skriv ett program som läser in en textrad och antal gånger som den skall skrivas ut och som sedan skriver ut texten, med följande utskrift: Ange en text: Jag gillar Java Antal gånget texten skall skrivas ut: 4 1: Jag gillar Java 2: Jag gillar Java 3: Jag gillar Java 4: Jag gillar Java Övning 1.5: Skriv ett program som läser in en sträng och som sedan skriver ut antal tecken, texten med versaler, ersätter alla mellanslag (’ ’) med bokstaven ’a’, samt skriver ut texten baklänges, enligt följande exempel: Ange en text: Jag gillar Java Antal tecken: 15 JAG GILLAR JAVA JagagillaraJava avaJ rallig gaJ Övning 1.6: Skriv ett program som läser in två namn och som sedan skriver ut dem i bokstavsordning med en if-sats, med följande utskrifter: Ange första namnet: kalle Ange andra namnet: anders I bokstavsordning: anders kalle Övning 1.7: Skriv ett program som läser in namn och som sedan sorterar dem och skriver ut dem i bokstavsording, med följande utskrifter: Hur många namn skall läsas in: 4 Skriv in namn 1: kalle Skriv in namn 2: eva Skriv in namn 3: anna Skriv in namn 4: bengt I bokstavsordning: anna, bengt, eva, kalle, Övning 1.8: Skriv ett program som beräknar hypoteunsan med Pythagoras sats avrundad till ett heltal, med följande utskrift: Ange ena kateten: 12 Ange andra kateten: 19 Hypotenusan avrundad till heltal: 22 Övning 1.9: 1 1 1 1 1 1 + + + + + ... + för olika värden på N. Vad blir summan om man 2 4 8 16 32 N tar med många termer? Beräkna summan /home/micko/Skrivbord/java_lektioner.doc 9 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson 2. Grafiska metoder Hittills har programmen körts i konsollfönstret. Java har dock stora grafiska möjligheter. Vi skall inledningsvis skapa ett fönster. Sedan fyller vi detta med linjer, polygoner och texter via grafiska metoder. Därefter lär vi oss att hantera grafiska komponenter som knappar och textrutor. Fönster (frame) I Java API (Application Programming Interface) finns paketet java.awt (Abstract Window Toolkit), som innehåller många klasser för hantering av grafik, text, färger och komponenter som knappar och textrutor. Ur detta paket behöver vi strax klasserna Graphics, Font och Color. Vi importerar dem därför med följande satser: import java.awt.Graphics; import java.awt.Font; import java.awt.Color; Eller kortare: import java.awt.*; Paketet java.awt innehåller en klass Frame, som automatiskt öppnar ett fönster när man skapar ett objekt av klassen. Eftersom vårt program skall ha samma egenskaper som klassen Frame, måste det ärva Frame:s egenskaper. Följande program skapar ett fönster: import java.awt.*; class test4 extends Frame{ //extends anger att klassen test4 ärver av Frame test4() { setBackground(Color.yellow); setSize(400,150); } //Konstruktor för klassen test4 //Anger fönstrets bakgrundsfärg //Anger fönstrets storlek public static void main(String args[]) { test4 d=new test4(); d.setVisible(true); } //Main-funktionen //Skapar objektet d av klassen test4 (fönstret skapas) //Fönstret görs synligt med Frame-metoden setVisible } Observera att fönstret inte kan stängas med systemknappen. Stäng istället via konsollfönstret. Färger Färgen kan även anges mer fritt på RGB-format. Ett ”färgobjekt” av klassen Color måste då först skapas: Color c=new Color(200,0,0); setBackground(c); //Skapar objektet c av klassen Color med RGB-färgen (200,0,0) d v s röd Följande färger finns fördefinierade (anges med Color.): black, blue, cyan, gray, darkGray, lightGray, green, magenta, orange, pink, red, white, yellow Övning 2.1: Kopiera och modifiera ovanstående programexempel så att bakgrunden får en slumpmässig färg varje gång fönstret öppnas. Övning 2.2: Modifiera föregående övning ytterligar så att även fönstrets storlek öppnas med slumpmässig storlek. /home/micko/Skrivbord/java_lektioner.doc 10 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Linje i fönster Klassen Graphics innehåller grafiska metoder som bl a ritar streck och polygoner, samt text. Följande program bygger vidare på förra exemplet och ritar en linje i fönstret: import java.awt.*; class test4 extends Frame{ test4() { setBackground(Color.yellow); setSize(400,400); } public void paint(Graphics g){ //Metoden paint anropas automatiskt när fönstret skapas g.setColor(Color.red); //Grafikfärg g.drawLine(100,100,300,300); //Linjen ritas mellan koordinaterna (100, 100) och (300, 300) } public static void main(String args[]) { test4 d=new test4(); d.setVisible(true); } } Observera att metoden paint anropas automatiskt när fönstret skapas eller ändras. Övning 2.3: Modifiera ovanstående exempel så att ett slumpmässigt antal (1-10) linjer ritas ut i fönstret med slumpmässiga färger. Fönstrets bakgrundsfärg skall vara grå. Text i fönster Följande program ritar en linje och lägger in text: import java.awt.*; class test4 extends Frame{ test4() { setBackground(Color.yellow); setSize(400,400); } public void paint(Graphics g){ g.setColor(Color.red); g.drawLine(100,100,300,300); g.drawString("Det funkar!",200,200); //Skriver ut en textsträng o koordinaten (200, 200) } public static void main(String args[]) { test4 d=new test4(); d.setVisible(true); } } Texten som skriv ut är oformaterad, men kan formateras med klassen Font. Följande rad visar ett exempel på hur texten kan formateras med Font-variabeln f (objektet f av klassen Font): Font f=new Font("Arial",Font.BOLD,24); //Typsnitt (ett fåtal stöds), stil, storlek För stilen finns även Font.ITALIC och Font.PLAIN. Kombinationer av olika stilar anges med: Font.BOLD+Font.ITALIC Följande programexempel illustrerar hur det fungerar genom att modifiera föregående exempel: /home/micko/Skrivbord/java_lektioner.doc 11 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson import java.awt.*; class test4 extends Frame{ Font f=new Font("Arial",Font.BOLD,24); test4() { setBackground(Color.yellow); setSize(400,400); } //Objektet f av klassen Font deklareras public void paint(Graphics g){ g.setColor(Color.red); g.drawLine(100,100,300,300); g.setColor(Color.green); //Grafikfärgen ändras för texten g.setFont(f); //Den valda fonten sätts g.drawString("Det funkar!",200,200); } public static void main(String args[]) { test4 d=new test4(); d.setVisible(true); } } Följande metoder finns för klassen Graphics: drawLine(x1,y1,x2,y2); drawRect(x,y,b,h); fillRect(x,y,b,h); drawRoundRect(x,y,b,h,m,n) fillRoundRect(x,y,b,h,m,n) draw3DRect(x,y,b,h,upp) fill3DRect(x,y,b,h,upp) drawOval(x,y,b,h) fillOval(x,y,b,h) drawArc(x,y,b,h,s,l) drawPolygon(xp,yp,n) fillPolygon(xp,yp,n) //Ritar en linje mellan koordinaterna (x1, y1) och (x2, y2) //Ritar en rektangel med övre vänstra hörnet i (x, y), bredd b och höjd h //Fyller rektangeln //Rektangel med rundade hörn, där m och n anger rundning //Fyller rundad rektangel //Tredimensionell rektangel, upp är tru elle false //Fyller en tredimensionell rektangel //Ritar en oval //Fyller en oval //Ritar en båge, där s är startpunkt ock I slitpunkt I grader //Ritar en polygon. Koordinaterna (n st) ligger i fälten xp och yp //Fyller polygonen Övning 2.4: Modifiera föregående övning så att fönstret fylls med 100 slumpmässigt utritade och färglagda cirklar med diametern 100 pixlar. Fönstrets bakgrundsfärg skall vara grå. *Övning 2.5: Modifiera föregående övning så att fönstret fylls med 10 slumpmässigt utritade och färglagda lika stora polygoner. Välj själv polygonens antal hörn och utseende i programkoden. Fönstrets bakgrundsfärg skall vara grå. /home/micko/Skrivbord/java_lektioner.doc 12 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Instansvariabler med konstruktor och objekt I förra exemplet var linjens ändpunkter i paint-metoden fixerade. Vill kunna variera ändpunkternas koordinater är det lämpligt att tilldela dem i main-metoden. Eftersom Java bygger på klasser måste klassen test4 först få instansvariabler (samma som datamedlemmar i C++) för ändpunkterna (x1, y1) och (x2, y2), som kan tilldelas antingen via en konstruktor eller via ett objekt. Nedan visas båda varianterna. Först med konstruktor: import java.awt.*; class test4 extends Frame{ Font f=new Font("Arial",Font.BOLD,24); int x1,y1,x2,y2; //Instansvariabler (datamedlemmar) test4(int a1,int b1,int a2,int b2) { //Variablerna tilldelas via konstruktorn x1=a1; y1=b1; x2=a2; y2=b2; setBackground(Color.yellow); setSize(400,400); } public void paint(Graphics g){ g.setColor(Color.red); g.drawLine(x1,y1,x2,y2); //Instansvariablerna används i metoden paint g.setColor(Color.green); g.setFont(f); g.drawString("Det funkar!",200,200); } public static void main(String args[]) { int x=0, y=50, v=200, w=250; test4 d=new test4(x,y,v,w); //Konstruktorn anropas d.setVisible(true); } } Följande exempel gör samma sak, men här tilldelas instansvariablerna via objektet d: import java.awt.*; class test4 extends Frame{ Font f=new Font("Arial",Font.BOLD,24); int x1,y1,x2,y2; test4() { setBackground(Color.yellow); setSize(400,400); } public void paint(Graphics g){ g.setColor(Color.red); g.drawLine(x1,y1,x2,y2); g.setColor(Color.green); g.setFont(f); g.drawString("Det funkar!",200,200); } public static void main(String args[]) { test4 d=new test4(); d.x1=100; //Instansvariablerna tilldelas via objektet d d.y1=50; d.x2=200; d.y2=350; d.setVisible(true); } } /home/micko/Skrivbord/java_lektioner.doc 13 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Inläsning av variabler Följande exempel visar hur koordinaterna läses in i main-metoden. Observera att inläsning och omvandling från string- till int-typ görs i en sats: import java.awt.*; import java.io.*; class test4 extends Frame{ Font f=new Font("Arial",Font.BOLD,24); int x1,y1,x2,y2; test4() { setBackground(Color.yellow); setSize(400,400); } //Objektet f av klassen Font deklareras public void paint(Graphics g){ g.setColor(Color.red); g.drawLine(x1,y1,x2,y2); g.setColor(Color.green); //Grafikfärgen ändras för texten g.setFont(f); //Den valda fonten sätts g.drawString("Det funkar!",200,200); } public static void main(String args[]) throws IOException { BufferedReader in=new BufferedReader(new InputStreamReader(System.in)); test4 d=new test4(); System.out.print("Ange första x-värdet: "); d.x1=Integer.parseInt(in.readLine()); //Inläsning och omvandling görs i en sats. System.out.print("Ange första y-värdet: "); d.y1=Integer.parseInt(in.readLine()); System.out.print("Ange andra x-värdet: "); d.x2=Integer.parseInt(in.readLine()); System.out.print("Ange andra y-värdet: "); d.y2=Integer.parseInt(in.readLine()); d.setVisible(true); } } Övning 2.6: Skriv ett program som frågar efter hur många hörn en polygon skall ha och som sedan läser in xoch y-koordinater och ritar/fyller polygonen. Ledning: Läs in antal hörn och koordinaterna i main-metoden i en for-loop: test4 d=new test4(); System.out.print("Ange antal hörn: "); d.ant_horn=Integer.parseInt(in.readLine()); for (int i=0;i<d.ant_horn;i++) { System.out.print("Ange x-värdet: "); d.xp[i]=Integer.parseInt(in.readLine()); System.out.print("Ange y-värdet: "); d.yp[i]=Integer.parseInt(in.readLine()); } Samt deklarera tre instansvariabler i klassen test4: int [] xp=new int[10]; int [] yp=new int[10]; int ant_horn; /home/micko/Skrivbord/java_lektioner.doc //Maximalt tio hörn //Anger antal hörnpunkter 14 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson 3. Applets och grafiska komponenter Hittills har vi skrivit fristående javaprogram, främst för att lära oss grunderna i språkets syntax. Ofta används dock javaprogram i samband med webbsidor och då behövs inte JDK:s javatolk för att köra/interpretera det kompilerade programmet (class-filen), eftersom de vanligaste webbläsarna kan köra javaprogram – s k javaapplets. En applet (förkortning av applikation) är alltså ett fristående javaprogram som kan köras av en webbläsare. Detta innebär att konsollmiljöns inläsningar inte fungerar i applet, där inläsningar istället görs via bl a textrutor som i Visual Basic. Detta återkommer vi till senare. Applets Vi börjar med att göra om exemplet på sidan 12 till en applet: import java.applet.Applet; import java.awt.*; public class test4 extends Applet{ //Klassen Applet i paketet applet importeras //Klassen test4 ärver egenskaperna från klassen Applet Font f; //Objektet f av klassen Font deklareras public void init() { //Metoden init anropas när test4 skapas, d v s först f=new Font("Arial",Font.BOLD,24); setBackground(Color.yellow); } public void paint(Graphics g){ //Metoden paint anropas när skärmen ändras g.setColor(Color.red); g.drawLine(100,100,300,300); g.setColor(Color.green); //Grafikfärgen ändras för texten g.setFont(f); //Den valda fonten sätts g.drawString("Det funkar!",200,200); } } Det finns tre huvudsakliga skillnader mellan ett fristående program och en applet: 1. Istället för från standardklassen Frame ärver klassen test4 sina egenskaper från standardklassen Applet, som har liknande egenskapre som Frame. Fönstret som klassen Applet skapar kan dock inte visas fristående utan webbläsaren. 2. En applet saknar en main-metod. Istället är det webbläsaren som skapar första objektet av klassen test4. 3. Klassen test4 saknar konstruktor. Initieringar görs istället i metoden init. Fönstrets storlek anges i webbläsaren. Programmet kompileras som förut till en class-fil, som exekveras av webbläsaren (se nedan). Appleten kan dock enkelt testköras med programmet AppletViewer via TextPad:s menyval Tools/Run Java Applet. Under menyvalet Applet i AppletViewer finns några funktioner. I webbläsaren körs appleten med följande HTML-kod: <html> <head> <title> Min hemsida </title> </head> <body> Detta är min hemsida. <applet code="test4.class" width=500 height=300> </body> </html> /home/micko/Skrivbord/java_lektioner.doc 15 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Attributet code får filnamnet för appleten, och attributen width och height ger fönstrets storlek. Spara HTML-koden i programmet Anteckningar med filändelsen .html (eller .htm) och öppna filen i webbläsaren. Alternativt sparas HTML-koden på motsvarande sätt i TextPad. Webbsidan kan sedan visas via menyvalet View/In Web Browser. Parametrar i HTML-koden Parametrar (variabler) i appleten kan anges i HTML-koden. I följande exempel anges texten som skall skrivas ut i appleten, samt textens storlek i HTML-koden. Först visas HTML-koden: <html> <head> <!--Kommentar i HTML--> <title> Min hemsida </title> </head> <body> Detta är min hemsida. <applet code="test4.class" width=500 height=300> <param name="t" value="Detta är texten"> <!--parametern t får värdet ”Detta är texten”--> <param name="storlek" value="80"> <!--parametern storlek får värdet 80--> </body> </html> Javaprogrammet läser in värdet på parametrarna t och storlek från HTML-filen: import java.applet.Applet; import java.awt.*; public class test4 extends Applet{ Font f; String text, textstorlek; int storlek; public void init() { textstorlek=getParameter("storlek"); //Värdet på parametern storlek hämtas till textstorlek storlek=Integer.parseInt(textstorlek); f=new Font("Arial",Font.BOLD,storlek); text=getParameter("t"); //Värdet på parametern t hämtas till variabeln text setBackground(Color.yellow); } public void paint(Graphics g){ g.setColor(Color.red); g.drawLine(100,100,300,300); g.setColor(Color.green); g.setFont(f); g.drawString(text,200,200); } //Grafikfärgen ändras för texten //Den valda fonten sätts //Texten skrivs ut via variabeln text } All hantering av grafik läggs alltså i metoden paint. Övning 3.1: Skriv och provkör en applet som ritar ut ett antal slumpmässigt placerade fyllda cirklar med slumpmässig färg. Antalet cirklar och cirklarnas storlek skall anges som parametrar i HTMLkoden. /home/micko/Skrivbord/java_lektioner.doc 16 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Grafiska komponenter Kommunikationen med javaprogram sker ofta via grafiska komponenter av samma typ som i Visual Basic. Java har för detta ett antal standardklasser för grafiska komponenter, såsom t ex knapp, label (etikett), kryssruta, alternativknapp, listruta, textruta och rullningslist. Samtliga klasser finns i paketet java.awt.*. Vi kommer nedan att ta upp dessa standardklasser och hur olika händelser hanteras, t ex knapp- och tangenttryckningar och musklickningar. Knapp Knappar skapas av klassen Button. Programmet nedan innehåller två knappar, som byter till röd respektive grön färg på bakgrunden: import java.applet.Applet; import java.awt.*; public class test4 extends Applet{ public void init() { setBackground(Color.yellow); Button knappA=new Button("Röd"); add(knappA); Button knappB=new Button("Grön"); add(knappB); } //Objektet knappA skapas med texter Röd //Knappen läggs ut i webbfönstret //Motsvarande för knapp med text Grön public boolean action(Event evt,Object arg){ String text=(String)arg; if (evt.target instanceof Button){ if (text.equals("Röd")) setBackground(Color.red); if (text.equals("Grön")) setBackground(Color.green); } return true; } //action reagerar på en händelse //arg innehåller knappens (komponentens) text //evt kollar typ av komponent (klass) } Observera att knapparna centreras i fönstret från vänster i den ordning de skapas. Senare kommer vi att placera ut dem på ett sätt vi själva väljer. Vi modifierar programmet så att en slumpmässig färg används när knappB aktiveras. Koden för detta läggs lämpligen i en egen metod slumpfarg. Programmet får då följande utseende: import java.applet.Applet; import java.awt.*; public class test4 extends Applet{ public void init() { setBackground(Color.yellow); Button knappA=new Button("Röd"); add(knappA); Button knappB=new Button("Slumpfärg"); add(knappB); } public void slumpfarg(){ int r=(int)Math.round(255*Math.random()); int g=(int)Math.round(255*Math.random()); int b=(int)Math.round(255*Math.random()); Color c=new Color(r,g,b); setBackground(c); /home/micko/Skrivbord/java_lektioner.doc 17 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson } public boolean action(Event evt,Object arg){ String text=(String)arg; if (evt.target instanceof Button){ if (text.equals("Röd")) setBackground(Color.red); if (text.equals("Slumpfärg")) slumpfarg(); } return true; } } Klassen Button har två konstruktorer för knappen k: Button k=new Button(); Button k=new Button(”Tryck”); //Ger en textlös knapp //Ger knappen texten Tryck Nedan visas några användbara metoder för textrutan t: k.setLabel(”Text”); String texten=k.getLabel(); //Placerar texten Text på knappen //Returnerar knapptexten till variabeln texten Textruta Textrutor skapas av klassen TextField. I programmet nedan färgas bakgrunden av den färg som matas in i textrutan: import java.applet.Applet; import java.awt.*; public class test4 extends Applet{ TextField rutan1; public void init() { setBackground(Color.yellow); Button knappA=new Button("Textfärg"); add(knappA); Button knappB=new Button("Slumpfärg"); add(knappB); rutan1=new TextField("Skriv här",10); add(rutan1); } //Objektet rutan1 skapas //Placerar textrutan I fönstret public void slumpfarg(){ int r=(int)Math.round(255*Math.random()); int g=(int)Math.round(255*Math.random()); int b=(int)Math.round(255*Math.random()); Color c=new Color(r,g,b); setBackground(c); } public void textfarg(){ if (rutan1.getText().equals("g")) //Metoden getText() returnerar texten i textrutan setBackground(Color.green); if (rutan1.getText().equals("r")) setBackground(Color.red); if (rutan1.getText().equals("b")) setBackground(Color.blue); if (rutan1.getText().equals("y")) setBackground(Color.yellow); } public boolean action(Event evt,Object arg){ /home/micko/Skrivbord/java_lektioner.doc 18 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson String text=(String)arg; if (evt.target instanceof Button){ if (text.equals("Textfärg")) textfarg(); if (text.equals("Slumpfärg")) slumpfarg(); } return true; //Metoden textfärg anropas } } Klassen TextField har några olika konstruktorer för en textruta t: TextField t=new TextField(); TextField t=new TextField(10); TextField t=new TextField("Skriv här"); TextField t=new TextField("Skriv här",n); //Ger ett tomt textfält //Ger ett textfält med plats för 10 tecken //Ger ett textfält med texten ”Skriv här” //Ger ett textfält med texten ”Skriv här” och med n positioner Nedan visas några användbara metoder för textrutan t: t.SetColumns(n) String texten=t.getText(); t.SetText(”Detta står i textrutan”); t.setEchoChar(’*’); t.selectAll(); t.select(i,j); texten=t.getSelectedText(); //Antal teckenpositioner sätts till n //Textrutans innehåll returneras alltid som typen String //Tilldelar textrutan en text //Hemlig text, en ’*’ visas istället för tecknen //All text markeras //Tecknen i till j markeras //Returnerar markerad text Etikett (label) Etiketter skapas av klassen Label. I programmet nedan skrivs innehållet i textrutan ut högerjusterat i en label när knappen aktiveras: import java.applet.Applet; import java.awt.*; public class test4 extends Applet{ TextField te; Label la; public void init() { setBackground(Color.yellow); Button knappA=new Button("Tryck"); add(knappA); te=new TextField("Skriv här",10); add(te); la=new Label("Detta är en label",Label.RIGHT); add(la); } public boolean action(Event evt,Object arg){ String text=(String)arg; if (evt.target instanceof Button){ if (text.equals("Tryck")) la.setText(te.getText()); } return true; } //Etiketten la skapas högerjusterad //Texten i textrutan tilldelas etiketten } /home/micko/Skrivbord/java_lektioner.doc 19 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Klassen Label har två konstruktorer för etiketten e: Label e=new Label(”Text i etikett”); Label e=new Label(”Text i etikett”,Label.RIGHT); //Skriver ut texten vänsterjusterad i etikettens textyta //Skriver ut texten högerjusterad; Label.RIGHT, //Label.LEFT och Label.CENTER finns Nedan visas några användbara metoder för etiketten e: e.setText(”Text”); String texten=e.getText(); e.setAligment(Label.CENTER); //Placerar texten Text i etiketten //Returnerar etiketttexten till variabeln texten //Centrerar texten Egenskaper hos komponenter Komponenternas färg, text, storlek och läge kan påverkas av bl a samma metoder som vi använt för hela fönstret: setBackground(c); setForegrund(c); setFont(f); setVisible(true/false); setSize(bredd, höjd); setLocation(x,y); //Påverkar bakgrundsfärg hos text och knapp //Påverkar textfärg //Anger textstil och storlek //Komponenten döljs med false //Anger komponentens bredd och höjd i pixlar. Görs efter initieringen i t ex paint //Placerar komponenten med övre vänstra hörnet i koordinaten (x,y) i t ex paint Nedan visas några exempel på färg- och textändringar för knapp, textruta och etikett: TextField t = new TextField("Skriv här!",10); Label e = new Label("Grön:",Label.RIGHT); Button b = new Button("Tryck"); Font f=new Font("Arial",Font.BOLD,24); Color c=new Color(200,200,0); e.setFont(f); //Etikettens text anges b.setVisible(false); //Knappen döljs e.setForeground(Color.green); //Etikettens text blir grön e.setBackground(c); //Etikettens bakgrund får färgen c t.setBackground(Color.blue); //Textrutans bakgrundsfärg blir blå e.setSize(50,15); //Etiketten får längden 50 och höjden 15 pixlar e.setLocation(10,100); //Lägger etiketten med övre vänstra hörnet i koordinaten (10,100) Övning 3.2: Skriv och kör en applet via ett HTML-dokument läser in och beräknar summan av två decimaltal, enligt urklippet intill. Ledning: Använd Double.parseDouble(text); för omvandling från text till double och String.valueOf(x) för omvandling från typen double till text. Övning 3.3: Modifiera föregående applet så att den istället beräknar hypotenusan till till två inmatade kateter. Övning 3.4: Skriv ett program där bakgrundsfärgen anges i tre textrutor på RGB-format (0-255). Följande skall gälla (se även urklipp): • Textfärgen på etiketten och i textrutan skall vara röd, grön respektive blå. • Etiketternas bakgrundsfärg skall vara samma som fönstrets bakgrundsfärg. Texten skall vara 24 p fet. /home/micko/Skrivbord/java_lektioner.doc 20 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Rullningslist (scrollbar) Rullningslisten skapas av klassen Scrollbar. I programmet nedan skrivs läget hos rullningslisten ut i en etikett: import java.applet.Applet; import java.awt.*; public class test4 extends Applet{ Label la; Scrollbar rull; public void init() { setBackground(Color.yellow); rull=new Scrollbar(Scrollbar.HORIZONTAL,50,10,0,110); //Rullningslistens konstruktor add(rull); la=new Label("50",Label.RIGHT); add(la); } public boolean handleEvent(Event evt){ //handleEvent hanterar händelser från rullningslist if (evt.target instanceof Scrollbar) la.setText(String.valueOf(rull.getValue())); //Läget hos rullningslisten skrivs ut i label return true; } } Observera att metoden action inte fungerar för rullningslister. Istället används metoden handleEvent. Klassen Scrollbar har följande konstruktor för rullningslisten r: Scrollbar r=new Scrollbar(Scrollbar.HORIZONTAL,position,knappbredd,min,max); Positionen avläses vid knappens vänstra sida (undre sida vid Scrollbar.VERTICAL). Om exempelvis min=0, max=100 och knappbredd=10 blir maximala positionen 90 när knappen ligger längst till höger. Nedan visas några användbara metoder för rullningslisten r: r.getValue(); r.setValue(n); r.getMaximum() r.getMinimum() //Ger position hos rullningslistens knapp som heltal //Sätter rullningslistens knapp till positionen n (heltal, även negativt) //Ger maxvärdet //Ger minvärdet Övning 3.5: Skriv ett program med tre rullningslister, med vilka bakgrundsfärgen kan justeras (0-255). Vald färg skrivs ut i respektive etikett på RGB-form. Etikettfärgen skall dessutom vara röd, grön och blå, samt deras bakgrundsfärg samma som fönstrets bakgrundsfärg, enligt urklippet till höger. Övning 3.6: Skriv en applet som fyller en kvadrat med den övertonade gråskalan i urklippet till höger. /home/micko/Skrivbord/java_lektioner.doc 21 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson 4. Mus- och tangenthändelser I förra kapitlet hanterades händelser vid knapptryckningar och ändringar hos en rullningslist. I detta kapitel skall vi ta hand om händelser hos mus och tangenter. Mushändelser Följande metoder hanterar händelser hos musen: mouseDown(Event evt, int x, int y) mouseUp(Event evt, int x, int y) mouseMove(Event evt, int x, int y) mouseDrag(Event evt, int x, int y) mouseEnter(Event evt, int x, int y) mouseExit(Event evt, int x, int y) //Ger markörens koordinat när en musknapp trycks ned //Ger markörens koordinat när en musknapp släpps upp //Ger markörens koordinat när musen rör sig //Samma som föregående, men när en musknapp är nedtryckt //Ger markörens koordinat när musen kommer in i fönstret //Ger markörens koordinat när musen lämnar fönstret Programmet nedan skriver ut markörens koordinat när musknappen trycks ned, släpps upp respektive när musen rör sig i tre olika etiketter: import java.applet.Applet; import java.awt.*; public class test4 extends Applet{ Label l1,l2,l3; public void init() { l1=new Label("MouseDown x=000 y=000",Label.LEFT); add(l1); l2=new Label("MouseUp x=000 y=000",Label.LEFT); add(l2); l3=new Label("MouseMove x=000 y=000",Label.LEFT); add(l3); } public boolean mouseDown(Event evt, int x, int y){ l1.setText("MouseDown x="+String.valueOf(x)+" y="+String.valueOf(y)); return true; } public boolean mouseUp(Event evt, int x, int y){ l2.setText("MouseUp x="+String.valueOf(x)+" y="+String.valueOf(y)); return true; } public boolean mouseMove(Event evt, int x, int y){ l3.setText("MouseMove x="+String.valueOf(x)+" y="+String.valueOf(y)); return true; } } /home/micko/Skrivbord/java_lektioner.doc 22 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Override på update Följande program skriver ut markörens koordinat med ritmetoden drawString där musknappen trycks ned: import java.applet.Applet; import java.awt.*; public class test4 extends Applet{ int x1,y1; //Globala variabler public void paint(Graphics g){ g.drawString("x="+String.valueOf(x1)+" y="+String.valueOf(y1),x1,y1); } public boolean mouseDown(Event evt, int x, int y){ x1=x; y1=y; repaint(); //Anropar metoden paint return true; } } Observera att den gamla koordinaten raderas vid varje ny musklickning. Detta beror på att metoden repaint även anropar metoden update, som målar över all grafik (dock inte komponenter som knappar och etiketter) med bakgrundsfärgen. Genom att göra en omdefiniering av update så att den anropar paint utan att rita om bakgrunden, kommer även de gamla koordinaterna att visas. Att omdefiniera en metod kallas override. Följande program visar hur det fungerar: import java.applet.Applet; import java.awt.*; public class test4 extends Applet{ int x1=50, y1=50; //Startkoordinater för paint, som anropas när fönstret skapas public void paint(Graphics g){ g.drawString("x="+String.valueOf(x1)+" y="+String.valueOf(y1),x1,y1); } public void update(Graphics g){ paint(g); } //override på update public boolean mouseDown(Event evt, int x, int y){ x1=x; y1=y; repaint(); return true; } } Originalversionen av update har följande utseende: public void update(Graphics g){ g.setColor(getBackground()); g.fillRect(0,0,width,height); g.setColor(getForeground()); paint(g); } /home/micko/Skrivbord/java_lektioner.doc 23 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Övning 4.1: Skriv ett program som ritar ut en röd cirkel med diametern 20 punkter när musknappen klickas, enligt urklippet. Övning 4.2: Skriv ett program som ritar en linje mellan två punkter som klickar med musen. Övning 4.3: Skriv ett program som ritar en gul rektangel med röd ram med diagonalen mellan de två klickade punkterna. Observera att rekrangeln omges av en röd linje, samt att det inte spelar någon roll hur punkterna klickas, d v s om nedre eller övre punkten klickas först. Ledning: Använd funktionerna Math.min() och Math.abs(). Övning 4.4: Modifiera föregående övning så att rektangeln ritas ut i ’realtid’ med musknappen nedtryckt. Det skall även fungera att minska rektangelns storlek. När musknappen släpps och en ny rektangelpåbörjas raderas den gamla. Ledning: Gör inte override på update. Övning 4.5: Skriv ett program där man kan rita med musen när en knapp är nedtryckt. /home/micko/Skrivbord/java_lektioner.doc 24 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Rita utan paint Metoden paint anropas automatiskt när appleten startas. Ibland ställer detta till problem, t ex när variabler i paint ännu inte är initierade. Därför är det bättre att lägga kod som ritar figurer i en egendefinierad metod, som anropas från t ex en musmetod. Detta illustreras i följande exempel, där en kvadrat ritas ut vid varje musklickning. Programmet innehåller även en knapp som raderar fönstret: import java.applet.Applet; import java.awt.*; public class test4 extends Applet{ Button knapp; //Raderaknappen Graphics g; //Deklarera objektet g av klassen Graphics public void init() { g=getGraphics(); //Skapar objektet g. Observera get istället för new setBackground(Color.yellow); knapp=new Button("Radera"); add(knapp); } public boolean action(Event evt,Object arg){ repaint(); return true; } //Reagerar på knappen //Ritar om fönstret, d v s raderar public void rita(int x1, int y1){ g.setColor(Color.red); g.fillRect(x1-10,y1-10,20,20); } //Egen metod rita som ritar //Fyller en rektangel med markör i mitten public boolean mouseDown(Event evt, int x, int y){ rita(x,y); //Anropar egna funktionen rita. Skickar med x och y. return true; } } Observera att programmet innehåller den egendefinerade metoden rita, som ritar ut en kvadrat. Övning 4.6: Skriv ett program där man kan rita polygoner genom att klicka i hörnen med musen. Polygonen ritas när det sista hörnet klickas. Antal hörn matas in i textrutan. Det skall även finnas en knapp som raderar fönstret. Tangenthändelser Händelserna keyDown(Event evt, int key) och KeyUp(Event evt, int key) hanterar tangenttryckningar. Parametern key anger ASCII-koden för den nedtryckta tangenten och evt används för att kolla om Alt-, Ctrl- eller Skift-tangenten är nedtryckt: if (evt.controlDown()) if (evt.shiftDown()) if (evt.metaDown()) //true om Ctrl-tangen är nedtryckt //true om Skift-tangen är nedtryckt //true om Alt-tangen är nedtryckt /home/micko/Skrivbord/java_lektioner.doc 25 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Följande exempel skriver ut ASCII-koden och tecknet för den nedtryckta tangenten: import java.applet.Applet; import java.awt.*; public class test3 extends Applet{ String s=""; public void paint(Graphics g){ g.drawString(s,50,50); } public boolean keyDown(Event evt, int key){ s="ASCII-kod: "+String.valueOf(key)+" Tecken: "+(char)key; repaint(); return true; } } Observera att man måste klicka på appleten med musen en gång innan tangenthändelserna aktiveras. Det går heller inte att använda tangenthändelserna för att skriva ut text i komponenterna textrura och etikett. För vissa tangenter som saknar ASCII-kod, t ex piltangenterna, finns specialtecken: Event.HOME Event.END Event.PGUP Event.PGDN Event.UP Event.DOWN Event.LEFT Event.RIGHT //Home-tangenten //End-tangenten //Page Up-tangenten //Page Down-tangenten //Pil upp-tangenten //Pil ned-tangenten //Pil vänster-tangenten //Pil höger-tangenten Specialtecknen används på följande sätt: if(key==Event.LEFT) //Kollar om tangenten för pil vänster är nedtryckt Övning 4.7: Gör en applet där du kan flytta runt en kvadrat på skärmen med piltangenterna. Övning 4.8: Gör en applet där du kan rita en figur med pitangenterna med en liten punkt som penna. Trycker man på ’f’-tangenten kan flytta punkten på skärmen utan att det ritas ett streck. Trycker man på ’r’-tangenten ritar punkten ett streck efter sig när den flyttas. /home/micko/Skrivbord/java_lektioner.doc 26 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson 5. Animering med trådar Innan vi börjar animera skall vi presentera sex huvudmetoder som finns i klassen Applet (utom run). Två av dem, init och paint, har vi använt tidigare: init() Detta är den första metoden som körs när appleten laddas i webbläsaren. Här görs initieringar av t ex komponenter, globala variabler och av bakgrundsfärg. start() Efter att init anropats körs metoden start. Den används för att starta någon aktivitet, t ex en animering (se nedan). run() Metoden anropas efter att en aktivitet startats i metoden start, t ex att en tråd har startats (finns i gränssnittet Runnable, se nedan). stop() …kan användas för att stoppa en aktivitet. Metoden anropas automatisk när användaren lämnar webbsidan. Metoden används sällan i program. paint(Graphics g) Här placeras grafikrutinera för att rita på appleten. Metoden anropas automatiskt när appleten startas och när fönstrets storlek eller läge förändras. I tidigare exempel (s. 25) har vi visat hur man kan rita utan paint genom att deklarera en egen metod. destroy() Denna metod anropas automatiskt när appleten avslutas och webbfönstret stängs och frigör då allt allokerat minne. Metoden används sällan i program. Trådar och multitasking När ett program befinner sig i en loop är det normalt helt uppslukat av vad som händer i loopen och kan inte påverkas utifrån. Exempelvis går det inte att avbryta en loop via en knapptryckning. Med trådar (threads) kan man emellertid använda sig av s k multitasking, d v s programmet får då förmågan att reagera på yttre händelser trots att det är upptaget av en loop. För att detta skall fungera Java måste vi införa gränssnittet Runnable, som innehåller metoder för trådar. Först något om multipelt arv i Java. Multipelt arv och gränssnitt i Java I C++ använde vi ibland multipelt arv. Detta innebär att en klass kan ärva från flera klasser. I Java däremot kan en klass ärva från endast en klass (via extends). Java har dock begreppet gränssnitt, som är en samling av metoder som kan ’ärvas’ via kommandot implements. Klassen Thread och gränssnittet Runnable Klassen Thread har några metoder för att starta och stänga av trådar: Thread trad; trad.start(); trad.stop(); trad.suspend(); trad.resume(); Startar en tråd Stoppar en tråd Deaktiverar en tråd, d v s pausar tråden Återstartar en deaktiverad tråd Observera att dessa start och stop inte är samma som tillhör klassen Applet. I följande exempel ärver klassen test4 egenskaperna från klassen Applet, samt implementerar gränssnittet Runnable, som innehåller metoden run. Programmet flyttar en cirkel över skärmen så länge x<300 pixlar: /home/micko/Skrivbord/java_lektioner.doc 27 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson import java.applet.Applet; import java.awt.*; public class test4 extends Applet implements Runnable{ Thread trad; int x=10; public void start(){ if(trad==null) { trad=new Thread(this); trad.start(); } } public void run(){ while (x<300) { x++; repaint(); try {Thread.sleep(10);} catch (InterruptedException e){} } } //Metoden paint anropas när fönstret ritas om. //Skapar en fördröjning på 10 ms public void paint(Graphics g){ g.fillOval(x,100,20,20); } } Felmeddelandet som vid kompileringen är inget att bry sig om. Övning 5.1: Gör en applet som flyttar runt en cirkel slumpmässigt på skärmen med en fördröjning på 100 ms. Övning 5.2: Modifiera föregående program så att flyttningen kan startas respektive stoppas via två knappar. Övning 5.3: Gör en applet som ändrar bakgrundsfärgen från rött till blått via en animering. Två trådar Vitsen med trådar är ju att kunna köra flera processer samtidigt. Följande exempel visar hur två trådar ’processar’ två bollar oberoende av varandra. Metoden i metoden run avgör vilket tråd som för tillfället är aktiv. Bollarna startas (resume) och stoppas (suspend) med var sin knapp: import java.applet.Applet; import java.awt.*; public class test3 extends Applet implements Runnable{ Thread trad1,trad2; int x1=50,y1=50,x2=100,y2=100,paus; Button start,stopp; boolean tryck1=false, tryck2=false; public void init() { start=new Button("Blå"); stopp=new Button("Röd"); add(stopp); add(start); trad1=new Thread(this); /home/micko/Skrivbord/java_lektioner.doc 28 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson trad2=new Thread(this); } public void start(){ trad1.start(); trad1.suspend(); trad2.start(); trad2.suspend(); } public void stop(){ trad1.stop(); trad2.stop(); } public void run(){ while (true){ if (Thread.currentThread().equals(trad1)){ x1=(int)Math.round(300*Math.random()); y1=(int)Math.round(300*Math.random()); paus=1000; } if (Thread.currentThread().equals(trad2)){ x2=(int)Math.round(300*Math.random()); y2=(int)Math.round(300*Math.random()); paus=500; } repaint(); try {Thread.sleep(paus);} catch (InterruptedException e){} } } public void paint(Graphics g){ g.setColor(Color.red); g.fillOval(x1,y1,20,20); g.setColor(Color.blue); g.fillOval(x2,y2,20,20); } public boolean action(Event evt,Object arg){ String text=(String)arg; if (evt.target instanceof Button) if (text.equals("Röd")){ tryck1=!tryck1; if (tryck1) trad1.resume(); else trad1.suspend(); } if (text.equals("Blå")){ tryck2=!tryck2; if (tryck2) trad2.resume(); else trad2.suspend(); } return true; } } Trådar i egen klass I förra exemplet kördes de båda trådarna i samma run-metod i appleten. Detta är en liten ’halvdan’ parallellprocessering, eftersom trådarna startas samtidigt när run-metoden anropas. Genom att köra trådarna via en klass blir det mer uppenbart att trådarna exeveras parallellt. /home/micko/Skrivbord/java_lektioner.doc 29 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson Följande program fungerar som förra exemplet. Programmet använder dock den egna klassen Boll för trådar och grafik, samt inte gränssnittet Runnable: import java.applet.Applet; import java.awt.*; public class test3 extends Applet { public class Boll extends Thread{ private int x,y,tid; private Graphics gr=getGraphics(); private Color farg; Boll (int a,int b,Color f,int t){ x=a; y=b; farg=f; tid=t; } } //Egna klassen Boll ärver från klassen Thread //Konstruktor för klassen Boll public void run() { while (true){ x++; gr.setColor(farg); gr.fillOval(x,y,20,20); try {Thread.sleep(tid);} catch (InterruptedException e){} gr.setColor(Color.white); //Raderar och ritar om utan repaint gr.fillOval(x,y,20,20); if (x>getWidth()) //Ger fönstrets bredd x=0; } } //Definitionen för klassen Boll slutar Boll b1, b2; Button knappb, knappr; boolean tryck1=false, tryck2=false; //Två Boll-objekt deklareras public void init() { knappb=new Button("Blå"); knappr=new Button("Röd"); add(knappb); add(knappr); b1=new Boll(0,100,Color.red,10); b1.start(); b1.suspend(); b2=new Boll(0,200,Color.blue,20); b2.start(); b2.suspend(); } public boolean action(Event evt,Object arg){ String text=(String)arg; if (evt.target instanceof Button) if (text.equals("Röd")){ tryck1=!tryck1; if (tryck1) b1.resume(); else b1.suspend(); } if (text.equals("Blå")){ tryck2=!tryck2; /home/micko/Skrivbord/java_lektioner.doc 30 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson if (tryck2) b2.resume(); else b2.suspend(); } return true; } public void stop(){ b1.stop(); b2.stop(); } } Observera att bollarna raderas genom att de ritas om med bakgrundsfärgen innan de ritas i en ny position. Genom att inte använda repaint minskas flimret i animeringen. Övning 5.4: Modifiera exemplet ovan och gör så att en eller några bollar studsar med olika fart mellan fönstrets sidor. Övning 5.5: Gör en applet som innehåller 20 studsande bollar mellan fönstrets sidor. Skapa bollarna via en array och använd klassen Boll i föregående exempel. Bollarnas färg, fart och startposition skall vara slumpmässig. Låt gärna den slumpmässiga färgen i genereras i klassen Boll. /home/micko/Skrivbord/java_lektioner.doc 31 09-08-21 LEKTIONSGENOMGÅNGAR I JAVA av Anders Andersson 6. Klasser i egna filer Följande exempel använder klassen Test för att skriva ut en sträng. Klassen innehåller även två konstruktorer; en med och en utan parameter: import java.applet.Applet; import java.awt.*; public class test3 extends Applet{ public class Test{ private String namn; //Klassen Test definieras //Instansvariabeln namn deklareras public Test(String n){ namn=n; } //Konstruktor med parameter public Test(){ namn="Kalle Anka"; } //Konstruktor utan parameter public String skriv_namn(){ return namn; } //Metod skriv_namn för utskrift av variabeln namn definieras } //Slut på klassdefinitionen Test t1,t2; public void init() { t1=new Test(); t2=new Test("Musse Pigg"); } //Referensvariablerna (objekten) t1 och t2 deklareras //t1 initieras till att referera till ett objekt av klassen Test //t1 och t2 är en instans av klassen Test public void paint(Graphics g){ g.drawString(t1.skriv_namn()+" och "+t2.skriv_namn(),100,100); } } Egen klassfil Vi modifierar föregående program genom att spara klassen Test i filen Test.java och kompilera den i samma mapp som appleten test3.java. Programmet blir då något kortare: import java.applet.Applet; import java.awt.*; public class test3 extends Applet{ Test t1,t2; public void init() { t1=new Test(); t2=new Test("Musse Pigg"); } public void paint(Graphics g){ g.drawString(t1.skriv_namn()+" och "+t2.skriv_namn(),100,100); } } /home/micko/Skrivbord/java_lektioner.doc 32 09-08-21