5 Hausaufgabe — Java Applets Allgemeines zu allen Aufgabenblöcken: • Lesen Sie den jeweils einleitenden Aufgabentext und die Aufgabenstellung genau. Damit Sie erläuternden Text von den Aufgabenstellungen schnell unterscheiden können, sind die Aufgabentexte optisch durch einen Randbalken hervorgehoben. Pflichtaufgaben sind mit dickem Randbalken, freiwillig zu bearbeitende Aufgaben mit einem dünnen Seitenstrich markiert. • Bearbeiten Sie die Aufgaben zügig. Sollten sich bei der Bearbeitung Schwierigkeiten ergeben, die Sie nicht selber lösen können, so befragen Sie Ihren Betreuer (Hiwi) und bitten Sie ihn um Hilfestellung oder ergänzende Erläuterungen! Sie sollten sich nicht “stundenlang” an einem Problem “festbeißen”! • Lesen Sie in der angegebenen/empfohlenen Literatur und in unserem “Einführungstext” nach eigenem Ermessen zu den im folgenden angegebenen Inhalten des Aufgabenblocks. 1 TA 5.1 (30%) Legen Sie zur Bearbeitung und Strukturierung Ihrer Lösungen unter Ihrem Verzeichnis AB5 drei weitere Verzeichnisse TA1, TA2 und TA3 an und sortieren Sie Ihre Quellen und Ergebnisse entsprechend ein. 5.1 Java-Applets In allen bisherigen Aufgaben wurden mit Hilfe von Java klassische Programme entwickelt, welche immer volle Zugriffsrechte auf alle lokalen Ressourcen (Dateien, Geräte, ...) des Benutzers besitzen, der sie ausführt. Außerdem erfolgt die Interaktion zwischen diesen Programmen und ihren Benutzern im einfachsten Fall über Ein- und Ausgaben von Texten. Zur Motivation schauen Sie sich bitte ein paar Beispiele auf http://java.sun.com/applets/ jdk/1.4/index.html an, nur um zu sehen, was man mit Applets alles machen kann. Was Applets besonders macht Die im Java-Sprachgebrauch kurz als Applet bezeichneten kleinen Anwendungen entsprechen nicht diesem klassischen Muster; sprich, Applets haben immer eine grafische Benutzeroberfläche und haben in der Regel keinen Zugriff auf lokale Ressourcen. Außerdem werden Applets nicht — wie klassische Java-Anwendungen — mit einem Aufruf java Programm gestartet, sondern werden von Internetseiten aus in dem verwendeten Internet-Browser (MS Internet-Explorer, Mozilla, Firefox,...) gestartet. Warum Applets sicher sind Eine wichtige Einschränkung solcher Internetanwendungen ist, dass sie im Normalfall keinen Zugriff auf lokale Ressourcen des Benutzers haben sollten. Ein Benutzer, der eine Internetseite mit eingebautem Applet aufruft, sollte schließlich nicht unbewusst das Risiko eingehen müssen, dass ein von der Internetseite gestartetes Applet bösartige Dinge (wie Spionage oder Datenzerstörung) mit seinen privaten Daten betreibt. Die dazu notwendigen, einschränkenden Sicherheitsrichtlinien werden umgesetzt, indem Applets in einer speziellen Umgebung ausgeführt werden, in der Ihnen keine Möglichkeit gegeben wird, auf kritische Ressourcen zuzugreifen1 . 1 Eine möglicherweise interessante Ausnahme von dieser Regel wird auf der Internetseite http://java.sun.com/developer/onlineTraining/Programming/JDCBook/ signed.html beschrieben. Für dieses Aufgabenblatt brauchen Sie diese Ausnahme aller- 2 Wo Applets ausgeführt werden Die Sicherheitsrichtlinien erlauben es erst, Applets direkt aus dem Internet zu starten, ohne das Risiko des Benutzers signifikant zu erhöhen. JavaApplets können so in Internetseiten integriert werden, dass beim Betrachter die Illusion entsteht, das Applet würde im Internet ablaufen. Das ist allerdings nicht der Fall, sondern das Applet wird in einer Java-Erweiterung des verwendeten Internet-Browsers ausgeführt. Gibt man in die Adresszeile des Browsers eine Adresse einer Internetseite ein, welche ein Applet enthält, so wird der Bytecode dieses Applet auf den lokalen Computer geladen und dann in der entsprechenden Erweiterung des Browsers ausgeführt. 5.2 Programmierung von Java-Applets In diesem Abschnitt werden nun die technischen Details beschrieben, die Ihnen bei der Implementierung eines Java-Applets begegnen. Rein technisch sind Java Applets nichts weiter als Klassen, die eine durch Java vorgegebene Klasse mit dem Namen Applet erweitern. Das erweitern einer Klasse haben Sie schon bereits auf Aufgabenblatt 3 kennengelernt2 und hat hier exakt die gleiche Bedeutung wie bei Turtle-Klassen. 5.2.1 Ein minimales Applet Ein minimales Applet MinimalApplet wird in Listing 1 definiert und ist tatsächlich bereits ein lauffähiges Applet, nur dass es eben nichts tut. Wird dieses Applet auf einer Internetseiten eingebaut, so bleibt der für das Applet reservierte Bereich einfach weiß oder grau. 1 2 import java . applet .*; public class MinimalApplet extends Applet {} Listing 1: Minimales Java-Applet dings nicht. 2 Zur Erinnerung: Man definiert eine Klasse Erweitert als Erweiterung einer anderen Klasse Basis, indem man in der Deklarationszeile der Klasse Erweitert die Basisklasse hinter dem Schlüsselwort extends nennt. Im Beispiel also: class Erweitert extends Basis{} Die erweiterte Klasse Erweitert übernimmt automatisch alle Funktionen und Attribute der Basisklasse Basis. 3 5.2.2 Veränderung des vorgegebenen Applets Die folgenden Methoden werden von der Klasse Applet zur Verfügung gestellt und sind auch für diese Aufgabe relevant3 : Rückgabewert Methodenname Beschreibung void init() Wird vom Browser aufgerufen, wenn das Applet geladen ist. void start() Wird vom Browser aufgerufen, wenn das Applet ablaufen kann. void stop() Wird vom Browser aufgerufen, wenn das Applet seine Ausführung unterbrechen soll. void destroy() Wird vom Browser aufgerufen, wenn das Applet nicht mehr benötigt wird. Um den Zusammenhang zwischen den Methoden aus der Tabelle zu verstehen, soll Abbildung 1 helfen. Im Code aus Listing 1 werden die benannten Methoden nicht neu definiert, und die Vorgaben aus der Klasse Applet, welche erweitert wird, werden daher nicht überschrieben. Falls Sie an dem in der Basisklasse Applet vorgegebenen Verhalten etwas ändern wollen, so müssen Sie die Methode einfach überschreiben, indem Sie die entsprechende Methode in ihrem Applet erneut definieren. inactive init() active start() 1 2 3 4 5 6 7 import java . applet .*; public class CustomApplet extends Applet { public void init () { ... } } Listing 2: Minimales Java-Applet destroy() stop() running Abbildung 1: Zustandsautomat der Klasse Applet Die in Listing 2 gegebene Deklaration zeigt ein Beispiel für die Überladung der Methode init, ab Zeile 5 müsste dann der eigene Code zur Initialisierung plaziert werden. 3 Weitere Informationen zur Klasse Applet aus dem Paket java.applet finden Sie unter http://java.sun.com/j2se/1.4.2/docs/api/java/applet/Applet.html. 4 5.3 Internetseiten und Applets Internetseiten werden in einer speziellen formalen Sprache (HyperText Markup Language kurz HTML) geschrieben, welche es vor Allem erlaubt, Texte zu strukturieren und mit Bildern zu versehen. HTML hat für das Internet fundamentale Bedeutung und wird ihnen immer wieder begegnen, wenn Sie mit dem Internet arbeiten. Diese Sprache für Internetseiten soll hier nicht das Hauptthema sein, allerdings können Applets, wie oben beschrieben, nur von Internetseiten aus gestartet werden. Damit für diese Aufgabe nicht erst die Sprache HTML verstanden werden muss, fassen wir hier die Grundlagen in aller Kürze zusammen. Wir werden Ihnen dabei zeigen, wie Sie eine kleine Internetseite mit ihrem eigenen Applet selbst aufsetzen können. 5.3.1 HTML in aller Kürze Man kann HTML als eine Sprache verstehen, mit der man auf systematische Weise Texte markieren kann. Eine Marke hat in HTML einen Namen, wie z.B. big, welcher den entsprechend markierten Text größer schreibt. Eine Markierung macht man dabei, indem man Marker (sogenannte Tags) in den Text einbaut, der markiert, wo ein entsprechender Bereich beginnt, und natürlich auch wo er endet. Dazu gibt es für jede Art Tag (wie z.B. das bereits erwähnte big-Tag) jeweils ein startendes Tag (am Beispiel: <big> ) und ein beendendes Tag (am Beipiel: </big> ) am Ende eines größer zu schreibenden Bereichs. Start und End-Tags unterscheiden sich durch den ”/” vor dem Namen des Tags. 1 2 3 4 5 6 7 < html > < head > < title > Beschreibung der Seite </ title > </ head > < body > </ body > </ html > Listing 3: Minimale HTML Datei Wie in Listing 3 zu sehen ist, besteht ein HTML-Bereich (<html> bis </html>) aus einem Kopf-Bereich (<head> bis </head>), der in der Regel Informationen über den Text enthält4 und einem Körper-Bereich <body> bis </body> ), der die eigentlichen Informationen der Seite trägt5 . HTML-Tag und Attribute Tags, wie sie im letzten Abschnitt beschrieben werden, können auch erweiterte Eigenschaften (Attribute) besitzen. In 4 Diese werden z.B. von Internetsuchmaschinen wie GOOGLE benutzt. Mehr über die Sprache HTML erfahren Sie auf http://de.selfhtml.org, für diese Aufgaben brauchen Sie diese Informationen allerdings nicht. 5 5 diesem Fall hat ein Tag eine Form wie das table-Tag in Listing 4. In dem Ausdruck <table border="1"> ist border der Namen eines Attributs des table-Tags und ”1” ist der Wert des Attributes. Die Bedeutung der im Bereich der Tabelle in Listing 4 definierten Unterbereiche, tr (steht für table row ) und th (steht für table head ), kann man in Abbildung 2 sehen. Abbildung 2: Das Bild zeigt einen Webbrowsers, der die in Listing 4 deklarierte Tabelle darstellt. 1 2 3 4 5 6 7 8 9 10 < table border = " 1 " > < tr > < th > Titel 1 </ th > < th > Titel 2 </ th > </ tr > < tr > < td > Inhalt 1 </ td > < td > Inhalt 2 </ td > </ tr > </ table > Listing 4: HTML Beschreibung der Tabelle aus Abbildung 2. Das HTML-Tag <APPLET> Nun soll in aller Kürze gezeigt werden, wie Sie eine Internetseite mit einem integrierten Applet erstellen können. 1 2 < APPLET CODE = " applet . class " WIDTH = " 20 " HEIGHT = " 20 " > </ APPLET > Listing 5: Das APPLET-Tag APPLET-Tags können im body-Bereich einer HTML-Datei eingesetzt werden, um ein entsprechendes Applet an entsprechender Stelle in die Seite einzubauen. Dabei müssen zwingend die Klassendatei im Attribut CODE, die Breite 6 des Applet im Attribut WIDTH und die Höhe des Applet im Attribut HEIGHT angegeben werden6 . Die Größenangabe muss dabei in Bildpunkten (sogenannten Picture Elements kurz Pixels) erfolgen. Die Applet-Klassendatei, deren Name im Attribut CODE angegeben wird, muss dabei im gleichen Verzeichnis wie die HTML-Datei liegen. 5.4 Zusammenfassung Um ein Applet auf einer Internetseite zu integrieren, brauchen Sie also mindestens eine wie in Listing 6 aufgeführte HTML-Datei. 1 2 3 4 5 6 7 8 9 < html > < head > < title > Das Applet </ title > </ head > < body > < APPLET CODE = " applet . class " WIDTH = " 20 " HEIGHT = " 20 " > </ APPLET > </ body > </ html > Listing 6: Das APPLET-Tag in einem HTML-Dokument. Aufgaben: Zunächst müssen Sie ein paar Befehle auf der Kommandozeile eintippen, damit ihre private Webseite im Gauß-IT Zentrum aktiviert wird: Geben Sie nacheinander die folgenden Kommandos auf der Kommandozeile ein: 1. mkdir ~/public_html 2. fs setacl ~/public_html system:anyuser rl Das erste Kommando legt ein Verzeichnis public html in ihrem Benutzerverzeichnis an. Das zweite Kommando verändert die Zugriffsrechte auf dieses neue Verzeichnis, so dass andere Benutzer in diesem Verzeichnis lesen können. Die Zeichenkette rl im zweiten Kommando sagt übrigens Lesen (read) und Auflisten (list), kurz rl. Das war es im Prinzip schon, und Sie haben Ihre Internetseite aktiviert. Ihre Internetseite können Sie jetzt mit einem Browser besuchen oder mit dem Appletviewer von Java oder dem eingebauten Appletviewer von Eclipse öffnen. 1. Legen Sie ein minimales Applet MinimalApplet an, wie es in Listing 1 demonstriert wurde. 2. Schreiben sie eine HTML-Datei, welche das Applet aus Aufgabe 1 benutzt. Nennen Sie die Datei einfach Applet.html. 6 Weitere Attribute zum APPLET-Tag werden unter http://de.selfhtml.org/html/ multimedia/java_applets.htm besprochen. 7 So, nun haben Sie ihr erste eigene Internetseite mit integriertem Java-Applet fertig, nur macht dieses Applet im Moment noch nichts besonderes. Das soll sich ändern. 5.5 Ereignisbasierte Programmierung Wie bereits erwähnt ist die Benutzerschnittstellte von Java-Applets immer Grafik-orientiert. Das hat auch Auswirkungen auf die Art und Weise, wie man programmiert. Wo man in einem klassischen Programm einfach mit System.out.println() einen Text ausgibt und z.B. mit System.in.read() Eingaben von der Tastatur liest, so treten in der grafischen Programmierung Ereignisse in den Vordergrund, die z.B. von der Computer-Maus kommen. 5.5.1 Ereignisse Ein Ereignis in diesem Sinne ist eine Mausbewegung, ein Mausklick, ein Ziehen mit gedrückter Maustaste und vieles mehr. Damit ein Applet diese Ereignisse (engl. events) empfangen kann, muss der Programmierer zunächst garantieren, dass das Applet mit bestimmten Events auch etwas anfangen kann. Soll das Applet z.B. innerhalb seines Bereichs auf dem Bilschirm auf Mausbewegungen reagieren, so muss das Applet ganz bestimmte Methoden implementieren. Schauen Sie sich das Beispiel in Listing 7 genau an. 1 2 3 import java . applet .*; import java . awt .*; import java . awt . event .*; 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public class BlinkApplet extends Applet implements M o u se M o ti o n Li s t en e r { public void init (){ a d d M o u s e M o t i o n L i s t e n e r ( this ); setBackground ( Color . yellow ); } public void mouseMoved ( MouseEvent e ) { setBackground ( new Color (( int )( Math . random ()*255) , ( int )( Math . random ()*255) , ( int )( Math . random ()*255) ) ); repaint (); } public void mouseDragged ( MouseEvent e ) { } } Listing 7: Einfaches Applet, das auf Mausbewegungen reagiert. 8 Die ersten drei Zeilen des Listings 7 importieren zunächst wieder die notwendigen Klassen, aus den entsprechenden Bibliotheken. In Zeile 7 geschieht nun etwas neues: sie deklariert das Applet zu einem MouseMotionListener. Diese Deklaration teilt Java mit, dass das Applet auch Methoden zur Interpretation von Ereignisse hat, die durch Mausbewegungen ausgelöst werden. In Folge dieser Deklaration müssen natürlich auch die Methoden implementiert werden, die der MouseMotionListener voraussetzt, das wären in diesem Fall mouseMoved und mouseDragged7 In Zeile 10 wird durch den Aufruf von addMouseMotionListener( this );das aktive Applet als MouseMotionListener registriert. Damit ist das Applet auf Empfang geschaltet. Treten im Folgenden Ereignisse auf, für die sich das Applet registriert hat, so wird das Applet durch den Aufruf seiner entsprechenden Methode informiert. Dabei wir dem Applet in diesem Fall ein MouseEvent übergeben 8 . Ein MouseEvent hat wiederum Methoden, über die man genaueres über das Event erfahren kann, wie z.B.getX()zum Auslesen der x-Koordinate des Events undgetY()zum Auslesen der y-Koordinate des Events. Das Applet aus Listing 7 ändert zufällig seine Farbe, wenn man mit dem Mauszeiger über seinen Bildschirmbereich fährt. Schnittstellen MouseMotionListener ist dabei eine sogenannte Schnittstelle (Interface). 1 2 3 4 5 public interface M ou s eMo t i on L i st e n er { public void mouseMoved ( MouseEvent e ); public void mouseDragged ( MouseEvent e ); } Listing 8: Definition von MouseMotionListener. Listing 8 zeigt eine verkürzte Definition der Schnittstelle MouseMotionListener. Wir müssen sowas in diesem Kurs nicht selbst definieren, sondern sagen durch implements MouseMotionListener, wie in Zeile 7 in Listing 7 nur, dass wir die Methoden der Schnittstelle implementieren. Bei solchen Schnittstellen ist zu beachten, dass der Compiler auch überprüft, ob alle Methoden der Schnitstelle auch wirklich durch die definierte Klasse implementiert werden. Daher implementiert Listing 7 auch die eigentlich leere Methode mouseDragged9 7 Das wird unter 5.5.1 nochmal etwas genauer erklärt. Siehe http://java.sun.com/j2se/1.4.2/docs/api/java/awt/event/MouseEvent. html. 9 Eine Liste weiterer Listener findet sich unter http://java.sun.com/j2se/1.4.2/ docs/api/java/util/EventListener.html. 8 9 5.6 5.6.1 Applets selbst entwickeln Die Methodepaint Jedes Applet stellt eine Methode mit der folgenden Deklarationszeile zur Verfügung: 1 public void paint ( Graphics g ); Listing 9: Deklarationszeile der Methode paint Wie man sieht, bekommt die Methode auch ein Objekt der Klasse Graphics übergeben. Dieses Objekt können Sie wie eine Leinwand verstehen, auf der Sie unter Anderem mit den folgenden Methoden malen können10 : Methodenname Beschreibung drawLine(int x1, int y1, int x2, int y2) Malt eine Linie. drawOval(int x, int y, int width, int height) Malt ein Oval. fillOval(int x, int y, int width, int height) Malt ein ausgemates Oval. drawString(String str, int x, int y) Schreibt einen Text. Listing 10 demonstriert den Umgang mit der Methode paint. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java . applet .*; import java . awt .*; public class PaintDemo extends Applet { public void init () { setBackground ( Color . yellow ); } public void paint ( Graphics g ) { int appletWidth = getWidth (); int appletHeight = getHeight (); g . drawString ( " Das ist keine Kunst ! " , 20 , 20); for ( int i =0; i <100; i ++) { Color c = new Color (( int )( Math . random ()*255) , ( int )( Math . random ()*255) , ( int )( Math . random ()*255)); g . setColor ( c ); g . drawLine (( int )( Math . random ()* appletHeight ) , ( int )( Math . random ()* appletWidth ) , ( int )( Math . random ()* appletHeight ) , ( int )( Math . random ()* appletWidth )); } } 10 Unter http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Graphics.html finden sich weitere. 10 27 } Listing 10: Eine einfache paint-Methode 5.6.2 Der appletviewer Sie wissen bereits, dass Applets dazu gedacht sind, in Internetseiten integriert zu werden. Testet man die Funktionsweise eines Applet aber mit der Hilfe eines Webbrowsers, so muss man diesen nach jedem Test neu starten, da der Browser die einmal gestarteten Applet bis zu seiner Beendigung im Speicher behält. Das Testen von Applet in einem Browser ist daher sehr unkomfortabel. Java bietet aus diesem Grund einen eigenen kleinen Applet-Betrachter mit dem Namen appletviewer. Dieser appletviewer wird wie folgt gestartet: appletviewer seite.html Als Parameter muss man also die HTML-Datei übergeben, in der das zu testende Applet integriert ist. 11 Aufgaben: 1. Schreiben Sie das Beispiel aus Listing 10 ab. 2. Schreiben Sie eine passende HTML-Datei und starten Sie das Applet im appletviewer. 3. Verändern Sie die Größe des appletviewer. Sie werden sehen, dass die zufälligen Striche immer wieder neu, an immer wieder neuen Punkten gemalt werden. Erklären Sie dieses Phänomen. 4. Verändern Sie das Applet so, dass es Kreise der immer gleichen Größe 50 an zufälligen Positionen malt (Kreise sind spezielle Ovale!). TA 5.2 (70%) In Listing 10 wurden mit der Methode g.drawLine(random,random,random,random)100 Linien zufällig auf der Lein- wand verteilt. In der letzten Aufgabe haben Sie das Applet dann verändert, so dass es gleichgroße Kreise an zufällige Positionen zeichnet. Nun soll dieses Applet nochmal modifiziert werden. Die Stellen, an denen Kreise gezeichnet werden sollen, werden nun über die Maus vom Benutzer vorgegeben. Das Applet muss dazu für entsprechende Ereignisse (wie in Abschnitt 5.5.1 beschrieben) auf Empfang geschaltet werden. Dann soll mit jedem eintreffenden Klick ein neuer Kreis an die vom Ereignis gegebene Position gezeichnet werden. Damit das Applet Klick-Ereignisse empfangen kann, muss, anders als im Beispiel in Listing 7, die MouseListener-Schnittstelle anstelle der dort implementierten MouseMotionListener-Schnittstelle umgesetzt werden. Die Implementierung der MouseListener-Schnittstelle erfordert die Umsetzung folgender Methoden: 1 2 3 4 5 6 7 public interface MouseListener { public void mouseExited ( MouseEvent e ); public void mouseClicked ( MouseEvent e ); public void mouseEntered ( MouseEvent e ); public void mouseReleased ( MouseEvent e ); } Listing 11: Definition von MouseListener. 12 Aufgaben: 1. Schreiben Sie das Beispiel aus Listing 10 so um, dass es die Schnittstelle MouseListener implementiert. Will man nun das Programm umschreiben, so dass es bei Eintritt eines Ereignisses an die Stelle des Ereignisses einen Kreis malt, so stößt man an folgendes Problem: In den Methoden mouseClicked, mouseExited, mouseEntered, mouseReleased kann man nicht Zeichnen, da es kein Graphics-Objekt gibt, und in der Methode paint kommen die Signale nicht an. Wie kann man das lösen? Nun, wir spreichern das Event einfach in einer Variable ab, die auch in der paint-Methode sichtbar ist. So kann die Ereignisverarbeitung und deren Darstellung einfach getrennt werden. 1. Schreiben Sie das Applet um, sodass es an Stellen, an denen der Benutzer klickt, einen Kreis zeichnet. 5.7 Die Leinwand ist vergesslich Wie Sie beim Ausprobieren des zuletzt erstellten Applets sicher bemerkt haben, vergisst die Leinwand beim Aufruf von Paint alles, was bereits auf ihr gezeichnet wurde. Um ein richtiges Bild malen zu können, müsste man sich daher nicht nur das letzte Ereignis, sondern auch alle vorherigen merken. Das kann man sehr gut mit einer Liste umsetzen11 . In diesem Kurs gehen wir aber einen anderen Weg, wobei wir die Methode update kennen lernen. 5.7.1 Die Methode update Die im java.applet.Applet vorgegebene Methode update sieht aus wie in Listing 12. 1 2 3 4 5 6 7 public void update ( Graphics g ) { g . setColor ( getBackground ); g . fillRect (0 ,0 , width , height ); g . setColor ( getForeground ()); paint ( g ); } Listing 12: Definition der Methode update 11 http://java.sun.com/j2se/1.4.2/docs/api/java/util/List.html 13 Listing 12 zeigt, warum alle alten Punkte immer wieder von der Leinwand verschwinden. Wenn wir also die Methode update mit einer von uns geschriebenen Version überladen, dann können wir das Verhalten an unsere Anforderungen anpassen. Aufgaben: 1. Schreiben Sie das Applet so um, dass update nicht den Inhalt der Leinwand löscht. 2. Malen Sie etwas und fahren Sie dann mit einem anderen Fenster über ihre Leinwand, nun Verschwinden die Kreise wieder! Warum? 14