CuP - Java Achzehnte (und LETZTE!) Vorlesung : 1.Teil: Vergleiche Skriptum Kapitel 8.1 2.Teil: WIEDERHOLUNG . Montag, 9. Dezember 2002 Threads Ein Thread ist ein Programmteil der eigenständig laufen kann während zur selben Zeit noch andere Aufgaben erledigt werden können (Multitasking!) Ein Thread verlangt das Runnable-Interface und somit die Implementierung der Methode run( ) Die Methode run( ) kann Interrupt-Exceptions produzieren und verlangt daher ein Exception-Handling Zum Abfangen der Interrupt-Exception verwendet man die Kontrollstruktur try{ ... } catch(InterruptedException e){ ... } 9. Dezember 2002 CuP WS 2002/2003 2 Threads Generierung mit Hilfe des Interface Runnable Implementierung: ... implements Runnable{ .... } Deklaration: Thread thread1; Initialisierung (in der Methode start( )): thread1=new Thread(this); Start: thread1.start( ); Aktivierung durch die Methode: void run( ){ ... } 9. Dezember 2002 CuP WS 2002/2003 3 Implementierung eines Threads (1/2) import java.awt.*; import java.applet.Applet; public class AThread extends Applet implements Runnable{ // Interface private Thread meinThread; // Deklaration des Threads private int t=0; // Sekundenzähler public void start(){ meinThread=new Thread(this); meinThread.start(); } 9. Dezember 2002 // Initialisierung des Threads // Start des Threads CuP WS 2002/2003 4 Implementierung eines Threads (2/2) public void run(){ // Aktivierung des Threads while (true) { try { Thread.currentThread().sleep(1000); } catch(InterruptedException e){} t++; repaint(); } } public void paint(Graphics g){ g.drawString("Thread ist seit ” + t + " Sekunden aktiv!", 100,100); } } 9. Dezember 2002 CuP WS 2002/2003 5 Ein komplexeres Beispiel zu Threads import java.awt.event.*; import java.awt.*; import java.applet.Applet; public class Reflexionen1 extends Applet implements ActionListener{ private Button start, stop; private Ball [] ball =new Ball[20]; int anzahl=0; public void init(){ setSize(500,500); start = new Button("Start"); add(start); start.addActionListener(this); stop = new Button("Stop"); add(stop); stop.addActionListener(this); } 9. Dezember 2002 CuP WS 2002/2003 6 public void actionPerformed(ActionEvent e){ Graphics g=getGraphics(); g.setColor(Color.white); g.drawString("Anzahl der Baelle: "+anzahl,50,470); if(e.getSource() == start && anzahl < 20){ ball[anzahl]=new Ball(g); ball[anzahl].start(); anzahl++; } if (e.getSource() == stop && anzahl > 0) { anzahl--; ball[anzahl].stirb(); } g.setColor(Color.black); g.drawString("Anzahl der Baelle: "+anzahl,50,470); } } 9. Dezember 2002 CuP WS 2002/2003 7 class Ball extends Thread{ private Graphics g; private boolean springe; private int x, y; private String dirX="links", dirY="hinauf”; private int sizeX=400, sizeY=400; public Ball(Graphics h){ g=h; springe=true; x=(int)(Math.random()*380 + 50); y=(int)(Math.random()*380 + 50); } public void stirb(){ springe=false; g.setColor(Color.white); g.fillOval(x,y,20,20); } 9. Dezember 2002 CuP WS 2002/2003 8 public void run(){ while (springe) { g.setColor(Color.white); g.fillOval(x,y,20,20); if (dirX.equals("rechts")) x++; else x--; if (dirY.equals("hinunter")) y++; else y--; if(x == sizeX+30) dirX = "links"; if(x == 50) dirX = "rechts"; if(y == sizeY+30) dirY = "hinauf"; if(y == 50) dirY = "hinunter"; g.setColor(Color.black); g.drawRect(50,50,sizeX,sizeY); g.setColor(Color.red); g.fillOval(x,y,20,20); try { Thread.sleep(10); } catch (InterruptedException e){ System.err.println("sleep exception"); }}}} 9. Dezember 2002 CuP WS 2002/2003 9 Wiederholung des Beispiels aus der 16. Vorlesung: Eine Klasse SchneeFall erweitert die Klasse Applet Instanzvariable: Tabelle schneeDaten; TextField wert; Methoden: init: erzeugt ein Objekt der Klasse Tabelle schneeDaten erzeugt ein Objekt der Klasse Label markierung mit Beschriftung “Zahl eingeben und Komponente anklicken” und fügt dieses dem Applet hinzu erzeugt ein Objekt der Klasse TextField wert und fügt dieses dem Applet hinzu aktiviert den ActionListener für das Textfeld aktiviert den MouseListener für das Applet 9. Dezember 2002 CuP WS 2002/2003 10 paint: ruft eine Instanzmethode zeigen auf (ist in der Klasse Tabelle zu deklarieren) der Parameter g der Klasse Graphics wird nur weitergereicht Für den ActionListener und MouseListener sind noch folgende Methoden zu implementieren: actionPerformed: übernimmt einen Wert aus dem Textfeld wert und initialisiert damit die Instanzvariable neuerWert des Objekts schneeDaten mouseClicked: bestimmt die y-Koordinate des letzten Maus-Klicks und ruft eine Instanzmethode waehleKomponente mit diesem Pixelwert als Parameter auf (ist in der Klasse Tabelle zu deklarieren) führt die Methode repaint aus 9. Dezember 2002 CuP WS 2002/2003 11 mouseReleased, mousePressed, mouseEntered, mouseExited sind weitere Methoden, die vom Interface MouseListener verlangt werden und daher (wenn auch ohne Funktion) implementiert werden müssen 9. Dezember 2002 CuP WS 2002/2003 12 Die Klasse Tabelle Instanzvariable: int [ ] schnee; int index, neuerWert, summe; für die Schneewerte, den Feldindex, den aus dem Textfeld zu übernehmenden Wert, die Summe aller Schneewerte sowie tabellenGroesse, startX, startY, feldHoehe, feldBreite zur Vereinbarung von Konstanten Methoden: zeigen: hat ein Graphics-Objekt g als Parameter, das benötigt wird um die Zeichenmethoden drawRect und drawString verwenden zu können zeichnet 7 Rechtecke der Breite 60 und Höhe 20 untereinander übernimmt die Werte aus dem Feld schnee und schreibt sie in die Rechtecke ruft die Methode addiereWerte auf und gibt Wochenschneefall aus 9. Dezember 2002 CuP WS 2002/2003 13 waehleKomponente: hat die y-Koordinate eines Maus-Klicks als Parameter berechnet den zu dieser y-Koordinate gehörigen index eines Feldelements von schnee schreibt den Wert der Instanzvariablen neuerWert in das Feldelement schnee[index] setzeWert: weist der Instanzvariablen neuerWert jenen Wert zu, der als Parameter übergeben wird addiereWerte: berechnet den aktuellen Wert der Instanzvariablen summe durch Summation der 7 Feldelemente von schnee 9. Dezember 2002 CuP WS 2002/2003 14 Übungsbeispiel für den 2. KNW: Angabe: Schreiben Sie ein Applet zur graphischen Darstellung einer Analoguhr unter Verwendung des Timers. Das Ziffernblatt soll ein Kreis mit Mittelpunkt (200,150) und Radius 100 Pixel sein. Der Sekundenzeiger - eine Linie vom Mittelpunkt des Kreises zu einem am Kreis befindlichen Punkt (Länge 100 Pixel) - soll im Sekundentakt um 6° (also eine Sekunde) weiterhüpfen. Der Minutenzeiger soll die Länge 80 Pixel haben und einmal pro Minute um 6° weiterhüpfen. Den Stundenzeiger der Länge 70 Pixel lassen Sie der Einfachheit halber einmal pro Stunde um 30° weiterhüpfen. Verwenden Sie eine Hilfsklasse namens Uhr, welche die Methoden zum Zeichnen des Ziffernblatts und der drei Zeiger bereitstellt. Eine weitere Methode zum Mitzählen der verstrichenen Sekunden, Minuten und Stunden könnte sich als praktisch erweisen. 9. Dezember 2002 CuP WS 2002/2003 15 import java.awt.event.*; import java.awt.*; import java.applet.Applet; import javax.swing.*; public class Analoguhr extends Applet implements ActionListener{ private Timer timer; Uhr meineUhr=new Uhr(); public void init(){ timer = new Timer(1000,this); timer.start(); } public void paint(Graphics g){ meineUhr.tick(); meineUhr.ziffernblatt(g); meineUhr.sekundenzeiger(g); meineUhr.minutenzeiger(g); meineUhr.stundenzeiger(g); } public void actionPerformed(ActionEvent e){ if(e.getSource() == timer) repaint(); } } 9. Dezember 2002 CuP WS 2002/2003 16 class Uhr{ int sek=0,min,std; public void tick(){ sek++; if (sek==60) { min++; sek=0; } if (min==60) { std++; min=0; } if (std==12) std=0; } public void ziffernblatt(Graphics g){ g.drawOval(100,50,200,200); } 9. Dezember 2002 CuP WS 2002/2003 17 public void sekundenzeiger(Graphics g){ int xSek=(int)(200.0 + 100.0*Math.sin(2.0*Math.PI*sek/60.0)); int ySek=(int)(150.0 - 100.0*Math.cos(2.0*Math.PI*sek/60.0)); g.drawLine(200,150,xSek,ySek); } public void minutenzeiger(Graphics g){ int xMin=(int)(200.0 + 80.0*Math.sin(2.0*Math.PI*min/60.0)); int yMin=(int)(150.0 - 80.0*Math.cos(2.0*Math.PI*min/60.0)); g.drawLine(200,150,xMin,yMin); } public void stundenzeiger(Graphics g){ int xStd=(int)(200.0 + 70.0*Math.sin(2.0*Math.PI*std/12.0)); int yStd=(int)(150.0 - 70.0*Math.cos(2.0*Math.PI*std/12.0)); g.drawLine(200,150,xStd,yStd); } } 9. Dezember 2002 CuP WS 2002/2003 18 Ein weiteres Beispiel: Angabe: Schreiben Sie ein Applet, welches ein Spiel mit einem einarmigen Banditen simuliert. Über ein Textfeld soll der einzuwerfende Geldbetrag - dieser betrage einen Euro - eingelesen werden, sobald ein Button “Neues Spiel” gedrückt wird. Drei weitere nebeneinander plazierte Schaltflächen sollen die Bedienung des (virtuellen) Spielautomaten erlauben. Beim Einwurf von einem Euro sind 3 Knopfdrucke erlaubt. Beim Drücken jedes der drei Buttons soll eine Zufallszahl im Bereich 1 bis 7 generiert werden und jeweils unterhalb der entsprechenden Schaltfläche ausgegeben werden. Bei drei gleichen Zufallszahlen ergibt sich ein Gewinn von 10 Euro, bei zwei gleichen ein Gewinn von 2 Euro. Der Gewinn (oder Verlust) soll in Form eines Antworttextes ausgegeben werden. Eine Hilfsklasse Automat soll die Methoden des Spielautomaten bereitstellen. 9. Dezember 2002 CuP WS 2002/2003 19 import java.awt.event.*; import java.awt.*; import java.applet.Applet; public class Bandit extends Applet implements ActionListener{ private TextField eingabe; private Button k1, k2, k3, neuesSpiel; String muenze; int gespielt=0; Automat a=new Automat(); public void init(){ eingabe=new TextField(2); add(eingabe); k1=new Button("Zahl 1"); add(k1); k1.addActionListener(this); k2=new Button("Zahl 2"); add(k2); k2.addActionListener(this); k3=new Button("Zahl 3"); add(k3); k3.addActionListener(this); neuesSpiel=new Button("Neues Spiel"); add(neuesSpiel); neuesSpiel.addActionListener(this); } public void actionPerformed(ActionEvent e){ Graphics g=getGraphics(); if (e.getSource() == k1 && !a.gameOver){ a.zufallszahl(g,1); gespielt++; } 9. Dezember 2002 CuP WS 2002/2003 20 if (e.getSource() == k2 && !a.gameOver){ a.zufallszahl(g,2); gespielt++; } if (e.getSource() == k3 && !a.gameOver){ a.zufallszahl(g,3); gespielt++; } if (e.getSource() == neuesSpiel){ gespielt=0; muenze=eingabe.getText(); if (muenze.equals("1")){ a.gameOver=false; a.spiel(g); } else{ a.gameOver=true; g.clearRect(100,90,200,100); g.drawString("Bitte 1 Euro einwerfen!!!",100,150); } } if (gespielt==3){ a.gameOver=true; a.gewinnausgabe(g); } } } 9. Dezember 2002 CuP WS 2002/2003 21 class Automat{ int [] zahl=new int[3]; boolean gameOver = true; public void spiel(Graphics g){ zahl[0]=8; zahl[1]=9; zahl[2]=10; g.clearRect(100,90,200,100); } public void zufallszahl(Graphics g, int i){ zahl[i-1]=(int)(Math.random()*7+1); g.clearRect(100+i*40,90,20,20); g.drawString(Integer.toString(zahl[i-1]),100+i*40,100); } public void gewinnausgabe(Graphics g){ if (zahl[0]==zahl[1] && zahl[1]==zahl[2]) g.drawString("Sie haben 10 Euro gewonnen!!!",100,150); else if (zahl[0]==zahl[1] || zahl[0]==zahl[2] || zahl[1]==zahl[2]) g.drawString("Sie haben 2 Euro gewonnen!!!",100,150); else g.drawString("Sie haben verloren!!!",100,150); } } 9. Dezember 2002 CuP WS 2002/2003 22 Kontrollfragen Was ist event-handling? Welches Paket muss fürs event-handling importiert werden? Welche Steuerflächen verlangen nach der Schnittstelle ActionListener? Wie wird ein Textfeld deklariert und instanziert? Wie heißt die Methode, die Veränderungen in einem Listenfeld detektieren kann? 9. Dezember 2002 CuP WS 2002/2003 23 Was ist bei der Verwendung eines Interface zu beachten? Welche Schritte sind für die Implementierung eines Timers nötig? Nennen Sie drei Methoden, die bei der Ausführung eines Java-Applets automatisch aufgerufen werden? Was bedeutet Vererbung? Erklären Sie die Begriffe Überschreiben und Überladen. 9. Dezember 2002 CuP WS 2002/2003 24 Frohe Weihnachten und einen Guten Rutsch ins Neue Jahr! ... und geniessen Sie die Ferien, Sie haben sie verdient :) JK