FHZ —> FACHHOCHSCHULE ZENTRALSCHWEIZ HTA —> HOCHSCHULE FÜR TECHNIK+ARCHITEKTUR LUZERN Elektrotechnik Informatik II - Übungen Louis-Pierre Gagnaux Inhaltsverzeichnis 1 Zahlenspeicher als Liste ........................................................................................................................2 2 Binärer Baum.........................................................................................................................................3 3 Hashing .................................................................................................................................................4 4 Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java..............5 4.1 Einfache Windows-Applikation mit Java.........................................................................................5 4.2 Erstellen von Windows-Applikationen mit der IDE von Forte4Java ................................................7 4.3 Erstellen einer Menuleiste, eines Pulldown-Menu und einem Menu-Item.....................................10 4.4 Linie zeichnen ..............................................................................................................................13 4.5 Einen Dialog um die Farbe und Strichdicke der zu zeichnenden Linie festzulegen ......................15 5 Mastermind..........................................................................................................................................17 System Charter.......................................................................................................................................17 5.2 Anforderungsspezifikation............................................................................................................18 5.3 Design..........................................................................................................................................18 5.4 Implementierung ..........................................................................................................................18 6 Übung zu Design-Patterns...................................................................................................................19 HTA LUZERN Louis-Pierre Gagnaux Technikumstrasse 21 [email protected] CH—6048 Horw www.gagnaux.ch Zahlenspeicher als Liste 1 Zahlenspeicher als Liste Lernziele Anwendung von dynamischen Datenstrukturen und von Datenstrukturen für effizientes Suchen und Einfügen. Aufgaben a) Implementieren Sie eine Klasse ‚ZS’, womit sie eine beliebige Anzahl von Zahlen speichern können. Implementieren Sie eine sortiert dynamisch wachsende, doppelt verkettete Liste. Die Klasse ‚ZS’ soll folgende Schnittstelle implementieren: public interface IZS { /** Fügt die Zahl z in den Zahlenspeicher */ public void add(int z); /** Gibt true, wenn Zahl z im Zahlenspeicher ist */ public boolean istIn(int z); public final byte AUFSTEIGEND=0; public final byte ABSTEIGEND=1; /** Druckt alle Zahlen des Zahlenspeichers auf den Bildschirm, falls order = 0 beginnend mit der grössten Zahl = 1 beginnend mit der kleinsten Zahl */ public void ausgabe(byte order); } b) Optimieren sie das Einfügen in die Liste, indem Sie mit Dummy-Elementen Fallunterscheidungen wie Liste leer, Einfügen am Anfang und am Ende und Einfügen in die Mitte der Liste verhindern. Optimieren Sie auch das Auffinden einer Zahl (Methode ‚boolean IstIn(int z)‘), indem Sie nur eine Abbruchbedingung der Suchschleife programmieren. c) Programmieren sie Klasse ‚ZS’ unter Verwendung der Java-API-Standard-Klasse ‚LinkedList‘. Verwenden Sie für das Traversieren der Liste einen ListIterator, der einen effizienteres Zugreifen ermöglicht als die ‚get(int index)‘ Methode. Da die Klasse ‚LinkedList‘ keine einfachen Datentypen speichern kann, sondern nur Objektreferenzen vom Typ ‚Object‘, müssen Sie die Zahlen über die Wrapper-Klasse ‚Integer‘ in die Liste speichern, siehe S. 144 in Go2001. Die Beschreibung der Java-API-Standard-Klassen ‚LinkedList‘ und ‚ListIterator‘ finden sie in der Java-API-Dokumentation im Package ‚java.util‘. d) Implementieren sie den Zahlenspeicher als Singleton, so dass es nur ein Objekt dieser Klasse kreiert werden kann, bzw. garantiert wird, dass nur ein Objekt davon existieren kann. e) Implementieren sie einen Visitor nach dem Visitor-Pattern, womit Sie den Zahlenspeicher unabhängig von der Implementierung traversieren können. Seite 2 9. June 2003 Informatik II - Übungen Binärer Baum 2 Binärer Baum Lernziele • Dynamische Datenstrukturen: Binärer Baum • Rekursive Programmierung Aufgabe a) Ändern Sie die Implementierung der Datenkapsel ‚ZS’ aus Aufgabe 1 „Zahlenspeicher als Liste“, so dass die Zahlen in einem binären Baum gespeichert werden und so, dass die Schnittstelle ‚IZS’ immer noch erfüllt bleibt. b) Definieren eine Methode, welches das Löschen von Elementen erlaubt, natürlich nur wenn sich das Element im binären Baum befindet. c) Programmieren sie Klasse ‚ZS’ unter Verwendung der Java-API-Standard-Klasse ‚TreeSet‘. Die Beschreibung der Java-API-Standard-Klassen ‚TreeSet‘ finden sie in der Java-API-Dokumentation im Package ‚java.util‘. Seite 3 9. June 2003 Informatik II - Übungen Hashing 3 Hashing a) Implementieren sie bei der Aufgabe „Häufigkeit von Wörtern“ aus dem 1.Semester die Filterklasse ‚Filter’ als Hash-Filter, der die trivialen Wörter wie ‚die’, ’der’, ’das’, ’ein’, etc. mit einem Hash-Algorithmus ausfiltern soll. Zur Erinnerung, die Klasse ‚Parser’ zerlegt den eingegebenen Text in Zeichen, Wörter und Zeilen. Die Klasse ‚WrdTab’ speichert Wörter mit deren Häufigkeit und kann diese dann ausgeben. Die Filterklasse ‚Filter’ überprüft mit der Methode ‚trivial(String wort)’, ob es sich um ein triviales Wort handelt. Das ergibt folgendes Klassen- und Interaktionsdiagramm. Filter main f : Filter wrdTab : Wrd Tab _worte Filter( ) trivial( ) p : Parser Filter ( ) WrdTab (f) 1 _filter Parser (wrdTab) parse ( ) WrdTab _tab _anzahlWorte zeile ( ) WrdTab( ) fuegeWortEin( ) druckeWortListe( ) wort ( ) trivial (wort) 1 _tab fuegeWortEin ( wort) druckeWortListe ( ) Parser _zeichen _worte _zeilen Parser( ) parse( ) statistik( ) zeile( ) wort( ) whitespace( ) b) Implementieren sie die Klasse ‚Filter’ unter Verwendung der Java-API-Standard-Klasse ‚HashSet‘. Die Beschreibung der Java-API-Standard-Klassen ‚HashSet‘ finden sie in der Java-API-Dokumentation im Package ‚java.util‘. c) Implementieren sie die Klasse ‚WrdTab’ unter Verwendung der Java-API-Standard-Klasse ‚TreeSet’ und erreichen sie damit, dass die Anzahl Wörter nicht mehr auf 100 begrenzt ist, das Einfügen effizienter wird und eine geordnete Ausgabe aller Wörter erfolgen kann. Seite 4 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java 4 Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java 4.1 Einfache Windows-Applikation mit Java Ein einfaches Windows-Programm könnte so aussehen. public class Simple extends javax.swing.JFrame { //--------------------------------------------------------------------------/** Verschachtelte Klasse, die Maus-Ereignisse abfängt */ class MouseHandler extends java.awt.event.MouseAdapter { public void mousePressed(java.awt.event.MouseEvent evt) { javax.swing.JOptionPane.showMessageDialog(null, "Sie haben die Maus gedrueckt"); } } //--------------------------------------------------------------------------/** Konstruktor */ public Simple() { super("Simple"); // Titelleiste des Fensters setzen addMouseListener(new MouseHandler()); // Maus Ereignis Handler registrieren setSize(400, 300); // Grösse des Fensters setzen } /** * Main: Here starts the program */ public static void main(String args[]) { Simple s=new Simple(); s.show(); } } Dieses Programm besteht aus der Klasse ‚Simple‘ und der ‚main‘-Methode , wo nach dem Laden der Klasse die Ausführung des Programms beginnt. Danach wird ein Objekt der Klasse ‚Simple‘ kontruiert, die aber nicht nur eine einfache Klasse ist, sondern von der Klasse ‚JFrame‘ abgeleitet ist und damit alles Verhalten einer leeren Windows-Applikation erbt. Jede einfache Java-Windows-Applikation besteht aus einer Fensterklasse und muss sein Fenster mit einer von ‚JFrame‘ abgeleiteten Klasse definieren. Nach dem Kreieren des Fensterobjekts wird mit der Mthode ‚show()’ eine endlose Schleife gestartet, die erst abgebrochen wird, wenn das Fenster geschlossen wird. Diese einfache Applikation reagiert auch auf Mausklicks. Wenn Sie die Maustaste betätigen, kommt ein einfaches Meldungsfenster (Message Box) mit der Nachricht „Sie haben die Maus gedrückt“, dass sie jeweils schliessen müssen. Dies wird mit der folgenden Klassenmethode erreicht: javax.swing.JOptionPane.showMessageDialog(null, "Sie haben die Maus gedrueckt"); Mit dem ersten Parameter wird das übergeordnete Fenster übergeben. Damit kann das Meldungsfenster innerhalb des übergeordneten Fensters zentriert werden. Wir können auch ‚null’ übergeben, das Meldungsfenster hat dann kein übergeordnetes Fenster und wird mitten auf dem Bildschirm positioniert. Wir werden dann später noch herausfinden, wie wir das übergeordnete Fenster mitgeben können. Der zweite Parameter bestimmt die Textausgabe auf dem Meldungsfenster. Seite 5 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java Abfangen von Mausbotschaften Um ein Fenster zu Programmieren, dass auf Botschaften der Maus reagieren soll, muss man ein Objekt beim Fenster registrieren, das ein bestimmtes Interface implementieren muss, bei Mausbotschaften das Interface ‚MouseListener’. Dieses Interface sieht wie folgt aus: public interface MouseMotionListener extends EventListener { public void mouseClicked(MouseEvent e); // Maus gedrückt und losgelassen public void mouseEntered(MouseEvent e); // Maus ins Fenster geschoben public void mouseExited(MouseEvent e); // Maus aus dem Fenster geschoben public void mousePressed(MouseEvent e); // Maus gedrückt public void mouseReleased(MouseEvent e); // Maus losgelassen } Man muss also eine Klasse definieren, die diese öffentlichen Methoden implementiert, die im Falle das die Maustaste gedrückt wird entsprechend aufgerufen werden. Zum Bespiel: Drückt man die Maustaste ohne loszulassen, wird die Methode ‚mousePressed’ des registrierten Objekts aufgerufen, beim Loslassen die Methoden ‚mouseReleased’ und ‚mouseClicked’ aufgerufen. Um nur ein bestimmtes Mausereignis abzufangen, wie z.B. nur das Drücken der Maustaste, ist es relativ kompliziert, eine Klasse zu programmieren, die alle Methoden implementieren muss und bei der Mehrheit der Methoden den Anweisungsteil leer lässt. Deshalb wird von der Java–API Klassen zur Verfügung gestellt, die diese Interface’s schon mit leerem Anweisungsteil implementieren. Zum Beispiel implementiert die Klasse ‚MouseAdapter’ das Interface ‚MouseListener’ mit leeren Methoden. Man muss nur noch eine abgeleitete Klasse definieren, die nur eine einzelne Methode überschreiben kann, wie dies im Beispiel mit der Klasse ‚MouseHandler’ erfolgt, die beim Drücken der Maus ein Meldungsfenster auf dem Bildschirm bringt: class MouseHandler extends java.awt.event.MouseAdapter { public void mousePressed(java.awt.event.MouseEvent evt) { javax.swing.JOptionPane.showMessageDialog(null, "Sie haben die Maus gedrueckt"); } } Das Registrieren des Maus-Behandlungsobjekt erfolgt mit der Methode ‚addMouseListener’, einer von der Klasse ‚JFrame’ geerbten Methode, wo als Parameter ein Objekt der selbstdefinierten Klasse ‚MouseHandler’ übergeben wird. Es gibt viele Ereignisse in einer Windows-Applikation, wie das Betätigen eines Menu, die Eingabe von Text oder das wenn ein Fenster den Fokus erhält. Alle diese Ereignisse werden nach dem selben Prinzip behandelt, wie eben gerade beschrieben. Ich werde im Folgenden einfach von einer Ereignisbehandlung reden. Aufgaben a) Finden Sie in der Java-API die Beschreibung der Methode ‚addMouseListener’. In welcher Klasse ist diese Methode definiert. b) Von welchem Typ ist der erste Parameter der Methode ‚addMouseListener’ Seite 6 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java 4.2 Erstellen von Windows-Applikationen mit der IDE von Forte4Java Integrierte Entwicklungsumgebungen (IDE) erlauben meistens mittels ein paar einfachen Klicks, das Erstellen von Windows-Applikation und generieren den notwendigen Code. Das Konzept bleibt hingegen das Gleiche. Das Generieren einer Windows-Applikation kann man mit einer Vorlage erreichen, indem man in der IDE eine entsprechende Vorlage für die Klasse auswählt, z.B. als Vorlage ‚JFrame’ auswählt, wie folgende Graphik zeigt. Man vergibt dann der zu generierenden Klasse einen Namen (‚Simple’) und erhält dann eine von der Klasse ‚JFrame’ abgeleitete Klasse mit dem Namen ‚Simple’. Man kann dann im ‚GUI Editing’-Register mit dem Form-Editor weitere Kontroll-Elemente wie Buttons, Check-Boxes graphisch editieren oder das Abfangen von Mausbotschaften definieren. Um den generierten Source-Code anschauen zu können, muss man aber ins ‚Editing’ Register wechseln. Wenn man eine solche Klasse graphisch verändern möchte, muss man diese doppelklicken. Möchte man hingegen den Source-Code anpassen, muss man zuerst die rechte Maustaste betätigen und das ‚Edit’ aus dem Popup-Menu auswählen. Das Abfangen von Mausbotschaften erfolgt dann, indem man mit der rechten Maustaste auf das entsprechende Kontroll-Element, in diesem Fall, das Hauptfenster der Applikation klickt und das entsprechende Ereignis auswählt, wie folgendes Bild zeigt. Seite 7 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java Wechselt man danach ins ‚Editing’ Register, findet man folgenden generierten Source-Code: public class GenSimple extends javax.swing.JFrame { /** Creates new form GenSimple */ public Simple() { initComponents(); } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() { addMouseListener(new java.awt.event.MouseAdapter() { public void mousePressed(java.awt.event.MouseEvent evt) { formMousePressed(evt); } }); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { exitForm(evt); } }); pack(); } private void formMousePressed(java.awt.event.MouseEvent evt) { // Add your handling code here: } Seite 8 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java /** Exit the Application */ private void exitForm(java.awt.event.WindowEvent evt) { System.exit(0); } /** * @param args the command line arguments */ public static void main(String args[]) { new Simple().show(); } // Variables declaration - do not modify // End of variables declaration } Die markierten Zeilen werden von der Entwicklungsumgebung verwaltet und können nicht verändert werden. Das Konzept für das Abfangen von Mausbotschaften ist gleich wie im ersten Beispiel. Es wird eine Klasse definiert, worin programmiert wird, wie auf Mausereignisse reagiert werden soll und danach ein Objekt dieser Klasse bei der Fensterklasse registriert. Der Unterschied ist, dass dies alles in einem Schritt mittels einer anonymen Klasse und mit folgendem Code realisiert wird. 1 addMouseListener( 2 new java.awt.event.MouseAdapter() { 3 public void mousePressed(java.awt.event.MouseEvent evt) { 4 formMousePressed(evt); 5 } 6 } 7 ); Auf der Zeile 1 erfolgt das Registrieren anhand der Methode ‚addMouseListener’. Als Parameter wird auf den den Zeilen 2-6 ein Objekt übergeben einer anonymen Klasse, die eben gleich in diesem Kontext definiert wird und dabei die Methode ‚mousePressed’ überschreibt. Diese ruft dann die Methode der Fensterklasse ‚formMousePressed(evt)’, wo sie dann ihren Code einfügen können. Aufgaben: a) Erstellen Sie mit Forte4Java eine entsprechende Windows-Applikation und programmieren Sie die Maustaste, dass diese beim Drücken ein Meldungsfenster auf dem Bildschirm bringt. b) Erweitern Sie die Aufgabe aus a) dass zusätzlich im Meldungsfenster angeben wird, welche Taste der Maus (linke, mittlere oder rechte) gedrückt wurde und an welcher Koordinaten-Stelle. Zum Beispiel: Hinweis: Suchen sie in der Java-API-Dokumentation die Beschreibung der MousEvent-Klasse. Seite 9 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java 4.3 Erstellen einer Menuleiste, eines Pulldown-Menu und einem Menu-Item Verwenden Sie dazu auch wieder die IDE von Forte4Java. Kreieren sie eine Applikation mit einer Fensterklasse, die von ‚JFrame’ abgeleitet ist und öffnen sie den Form-Editor (Doppelklick auf die Klasse). Sie finden am oberen Rand des Form-Editors sogenannte Kontrollelemente wie Button, CheckBox, Edit-Box usw. und unter anderem auch ein Kontrollelement für eine Menu-Leiste. Klicken sie diesen Knopf an und klicken sie anschliessend ins Fenster. Dann erhält automatisch das Fenster eine Menu-Leiste. Das geht für jedes andere Kontrollelement auch. Dann erhalten Sie folgendes Bild: Auf der rechten Seite finden sie hierarchisch angeordnet alle Kontrollelemente, dem Kontroll-ElementExplorer. Jedes Kontrollelement erhält einen eindeutigen Namen. Die soeben kreierte Menu-Leiste hat den Namen ‚jMenuBar1’ und ist vom Typ ‚JMenuBar’. Wir sehen auch, das mit der Menu-Leiste ein PulldownMenu mit Namen ‚jMenu1’ kreiert wurde, das hierarchisch der Menu-Leiste untergeordnet wird. Sie können diesen Kontrollelementen auch andere sinnvollere Namen geben. Im Eigenschaftsfenster, können sie die Eigenschaften des gerade selektierten Kontrollelement einsehen und verändern. Man kann z.B. dort den Namen des Pulldown-Menus abändern und je nach Kontrollelement Seite 10 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java vieles mehr. Mit einem rechten Mausklick auf das entsprechenden Pulldown-Menu können sie dann weitere Pulldown-Menus hinzufügen oder Menu-Items, mit dem dann eine Aktion ausgelöst werden kann. Mit einem Doppelklick auf das entsprechende Menu-Item im Kontrollelement-Explorer wird dann eine Aktions-Ereignisbehandlung kreiert und sie werden dann im Source-Editor positioniert, wo sie den entsprechenden Code einfügen können. Diese graphischen Werkzeuge erzielen nur eins, sie kreieren den entsprechenden Source-Code, den man danach erweitern kann oder muss. Für das genannte Bespiel mit einer MenuBar ‚jMenuBar1’, einem Menu ‚jMenu1’ und einem Menu-Item ‚jMenuItem1’ mit einer Aktionsbehandlung wird der folgende Source-Code in grau schattiert erzeugt. public class Menu extends javax.swing.JFrame { /** Creates new form Menu */ public Menu() { super("Menu"); // Titelleiste des Fensters setzen initComponents(); setSize(400, 300); // Grösse des Fensters setzen } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() { jMenuBar1 = new javax.swing.JMenuBar(); jMenu1 = new javax.swing.JMenu(); jMenuItem1 = new javax.swing.JMenuItem(); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { exitForm(evt); } }); jMenuBar1.setText("Menu"); jMenu1.setLabel("Item"); jMenuItem1.addActionListener(new java.awt.event.ActionListener() { Seite 11 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java public void actionPerformed(java.awt.event.ActionEvent evt) { _aboutActionPerformed(evt); } }); jMenu1.add(jMenuItem1); jMenuBar1.add(jMenu1); setJMenuBar(jMenuBar1); pack(); } private void _aboutActionPerformed(java.awt.event.ActionEvent evt) { // Add your handling code here: } /** Exit the Application */ private void exitForm(java.awt.event.WindowEvent evt) { System.exit(0); } /** * Main: Here starts the program */ public static void main(String args[]) { new Menu().show(); } // Variables declaration - do not modify private javax.swing.JMenuItem jMenuItem1; private javax.swing.JMenuBar _jMenuBar1; private javax.swing.JMenu jMenu1; // End of variables declaration } Aufgabe a) Kreieren Sie ein Windows-Applikation, mit einem ‚Help’-Pulldown-Menu und einem Item ‚About’, welches wenn angeklickt eine ‚Message Box’ aufbringen soll. Zum Beispiel: Seite 12 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java 4.4 Linie zeichnen a) Entwickeln sie ein Windows-Applikation die es erlaubt, eine Linie zu zeichnen. Kreieren sie eine Applikation mit einer Fensterklasse, die von ‚JFrame’ abgeleitet ist. Definieren Sie im Form-Editor, dass Ihr Fensterklasse eine Menuleiste und im Rest des Fensters ein ‚JPanel’ enthält. Das ‚JPanel’ ist die Komponente in der sie mit der Maus eine Linie zeichnen werden. Das graphische Zeichnen von Kurven und Flächen kann nicht direkt in einem ‚JFrame’ erfolgen, sondern ist nur in einer Komponente wie ‚JPanel’ möglich. Das Zeichnen einer Linie soll mit einem Mausklick und dem Ziehen der Maus erfolgen, d.h. mit dem Mausklick soll der Anfangspunkt und mit dem Loslassen der Maus der Endpunkt bestimmt werden. Sie müssen dabei die folgenden 3 Mausereignisse der Komponente ‚JPanel’ abfangen: • mousePressed von MouseAdapter • mouseReleased von MouseAdapter • mouseDragged von MouseMotionAdapter Während des Ziehen der Maus erhalten sie für jede Mausbewegung eine ‚mouseDragged’-Ereignis. Sie müssen damit jedes Mal die Linie neu zeichnen und die alte Linie löschen. Das Löschen der alten Linie können Sie bewirken, indem Sie die Linie nochmals mit der Hintergrund-Farbe zeichnen. Das Zeichnen einer Linie programmieren sie wie folgt: Graphics2D g=(Graphics2D) getGraphics(); g.setStroke(new BasicStroke(_stiftDicke)); g.setColor(Color.blue); g.drawLine(_startX, _startY, _endX, _endY); Mit Graphics2D g=(Graphics2D) getGraphics(); erhalten sie eine Referenz auf die graphische Geräteschnittstelle der gewünschten Komponente, hier also ‚this‘. Mit x g.setStroke(new BasicStroke(_stiftDicke)); (0,0) g.setColor(Color.blue); setzen sie die gewünschte Strichdicke und Farbe damit sie letztendlich mit g.drawLine(_startX, _startY, _endX, _endY); eine Linie zeichnen. Das Koordinatensystem beginnt in der linken oberen Ecke. Um eine Linie löschen zu können, setzen sie die Stiftfarbe wie folgt auf den Hintergrund: y g.setColor(getBackground()); Dies ist nicht die beste Art und Weise wie man einen Linien-Editor realisiert, weil damit eventuell schon gezeichnete Figuren im Hintergrund mit dem Zeichnen der Linie auch gelöscht werden. Es gibt eine elegantere Weise, wie man graphisch temporäre Figuren über einen beliebigen Hintergrund zeichnen kann und danach den Hintergrund wieder herstellen kann. Das können sie aus der Lösung entnehmen. b) Programmieren Sie auch, dass wenn das Fenster zum Beispiel in den Vordergrund bewegt wird (oder maximiert, nachdem es iconisiert wurde), nachdem es von einem anderen Fenster überdeckt war, die gezeichnete Linie im Fenster wieder gezeichnet wird. Das Erreichen sie, indem sie die Methode ‚paint’ mit der folgenden Parameter-Definition programmieren. Diese Methode wird für jede Komponente immer dann aufgerufen, nachdem ihr Fenster neu gezeichnet wurde, damit der Inhalt des Fenster neu gezeichnet werden kann. public void paint(Graphics g){ super.paint(g); // Aufruf der paint-Methode der Superklasse // Programmieren Sie hier das Neuzeichnen des Inhalts des Fensters } Seite 13 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java Hinweise Manchmal ist es notwendig ein Neuzeichnen einer Komponente explizit auszulösen. Das erreicht man, indem man der Komponenten die Botschaft ‚repaint()’ schickt, worauf die Komponente durch Aufruf der Methode ‚paint(Graphics g)’ neu gezeichnet wird. JFrame JPanel PaintPanel Linie _startX _startY _endX _endY _stiftFarbe _stiftDicke _paintArea main( ) initComponents( ) 1 _menuBar formMousePressed( ) formMouseReleased( ) formMouseDragged( ) paint( ) initComponents( ) 1 JMenu Man kann das Zeichnen mit der Maus im Hauptfenster ‚Linie’ definieren oder besser in einer separaten Klasse ‚PaintPanel’, das von der Klasse ‚JPanel’ abgeleitet ist. Erstellen Sie die Klasse ‚PaintPanel‘ , indem sie die Klassenvorlage ‚JPanel‘ verwenden. Das hat dann den Vorteil, dass das Zeichnen in einer Klasse verkapselt ist. Die Klasse ‚Linie’, muss dann statt ein ‚JPanel’ ein Objekt der Klasse ‚PaintPanel’ verwenden. Das zu programmieren ist gar nicht so einfach, da das Einfügen eines Panels über den Form-Editor erfolgt, welcher das Erzeugen des Source-Codes verwaltet und nicht erlaubt, dass dieser von Hand geändert werden kann. Sie können aber über das Eigenschaftsfenster des erzeugten Panels, im Register ‚Code Generation’ die Eigenschaft ‚Custom Creation Code’ auf ‚new PaintPanel()’ setzen, womit statt ein ‚JPanel’Objekt ein ‚PaintPanel’-Objekt verwendet wird. Seite 14 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java 4.5 Einen Dialog um die Farbe und Strichdicke der zu zeichnenden Linie festzulegen Erstellen Sie eine neue Klasse, z.B. mit Namen ‚LinienOptionen‘ als abgeleitete Klasse von ‚JDialog‘. Sie können auch hier eine Klassenvorlage von der Entwicklungsumgebung verwenden. Verwenden Sie hierfür einen Dialog der wie folgt aufgebaut ist und 3 Panels verwendet um die Kontrollelemente zu gruppieren: Panel 1 mit FlowLayout Panel 2 mit GridLayout Panel 3 mit FlowLayout Architektur JFrame JPanel JDialog _paintArea Linie 1 main( ) initComponents( ) _linienOptionenActionPerformed( ) _menuBar 1 JMenu LinienOptionen _linienOptionen jPanel1, jPanel2, jPanel3 1 JMenuItem _okActionPerformed( ) _cancelActionPerformed( ) _rot, _gruen, _blau, _strichDicke 3 _paintArea 1 PaintPanel _startX _startY _endX _endY _stiftFarbe _stiftDicke formMousePressed( ) formMouseReleased( ) formMouseDragged( ) paint( ) initComponents( ) _ok, _cancel JPanel * new LinienOptionen(this, true, (PaintPanel) paintArea). setVisible(true); 4 2 JTextField JButton * Den Dialog können Sie wie folgt aufstarten: new LinienOptionen(this, true, (PaintPanel) _paintArea).setVisible(true); Mit dem 1. Parameter übergeben sie das übergeordnete Fenster, mit dem 2. Parameter, dass es sich um einen modalen Dialog handelt und mit dem 3. Parameter übergeben sie die Referenz ‚paintArea‘ zum ‚PaintPanel‘-Objekt. Nachdem der Dialog aufgestartet ist, macht es Sinn die Kontrollelemente mit sinnvollen Werten zu setzen. Sie müssen dazu die Ereignisbehandlung ‚windowOpened‘ des Dialogs programmieren. Dieses Ereignis wird Seite 15 9. June 2003 Informatik II - Übungen Einführende Übungen zur Programmierung von graphischen Benutzerschnittstellen mit Java jedesmal ausgelöst wenn der Dialog geöffnet wird. Sie können dies auch im Konstruktur programmieren, aber erst nachdem die Komponenten initialisiert wurden. Wenn der ‚Ok‘-Button gedrückt wird, wird das Ereignis ‚actionPerformed‘ ausgelöst, womit sie in dieser Ereignisbehandlung die im Dialog veränderten Optionen dem ‚PaintPanel‘-Objekt zurückschreiben können. In der Ereignisbehandlung des Ereignis ‚actionPerformed‘ des ‚Cancel‘-Button müssen sie lediglich wie folgt den Dialog schliessen: setVisible(false); dispose(); Seite 16 9. June 2003 Informatik II - Übungen Mastermind 5 Mastermind 5.1 System Charter Es soll ein dem realen Mastermind ähnliches Spiel erstellt werden. Die Spielführung soll möglichst den Windows-Richtlinien entsprechen. Zum Beispiel sollen Stifte nach dem "Drag & Drop - Prinzip" positioniert werden können. Buchsen werden als leere Kreise, Stifte als gefüllte farbige Kreise dargestellt. Die linke Vierer-Buchsenspalte sind AntwortBuchsen, die rechte Vierer-Buchsenspalte sind Eingabebuchsen, wo der Spieler Stifte mit bestimmten Farben stecken kann. Das Füllen der Eingabebuchsen soll unten beginnen. 5.1.1 Spielablauf Der Computer bestimmt bei Spielbeginn 4 Stifte für jede Position von 1 bis 4 aus 8 möglichen Farben. Ein Spieler muss diese Kombinationen durch Erraten und Kombinieren herausfinden, indem er Eingabebuchsen mit Stiften bestückt. Abb. 1 Spielbrett Mastermind Das Setzen von Stiften erfolgt durch ein Anklicken einer der rechts stehenden vertikal angeordneten Auswahlstiften mit anschliessendem Ziehen zu einer Eingabebuchse. Ist eine ganze Reihe gesetzt, so kann der Spieler durch Drücken des Ok-Buttons eine Antwort vom Computer verlangen. Dieser antwortet • durch Setzen von schwarzen Stiften, wieviel Stifte mit der richtigen Farbe an der richtigen Position sind und • durch Setzen von grauen Stiften, wieviel Stifte nur die richtige Farbe haben aber noch nicht richtig positioniert sind. 5.1.2 Spielregeln • Ein Spieler hat 10 Versuche. • Stifte haben 8 mögliche Farben. • Die herauszufindende Kombination kann aus gleichfarbigen Stiften bestehen. Seite 17 9. June 2003 Informatik II - Übungen Mastermind 5.2 Anforderungsspezifikation Erstellen Sie eine Anforderungsspezifikation anhand von Use Cases. Mit Use Cases, engl. Anwendungsfälle des zu beschreibenden Systems, beschreibt man die verschiedenen Szenarien wie man das System benutzt. Dabei beschreibt man zuerst nur die positiven Fälle (keine „wenn dann Sätze“ verwenden) und führt später unter den Sonderfällen, die Ausnahmefälle auf. Das führt dazu, dass man relativ schnell, die funktionalen Anforderungen des Systems erfasst. Ein typischer Anwendungsfall ist, wie der Spieler einen Stift positioniert. Bestimmen Sie weitere Anwendungsfälle und beschreiben Sie diese. 5.3 Design a) Entwerfen sie ein Klassendiagramm, im Sinne eines objektorientierten Design. b) Verfeinern sie die Use Cases mit Interaktionsdiagrammen. c) Definieren sie, wie sie das Mastermind-Spiel verteilen wollen, als Applet oder als Swing-Applikation. 5.4 Implementierung Implementieren Sie das Mastermind-Spiel. Gehen Sie schrittweise wie folgt vor: a) Erstellen sie eine Windows-Applikation, die aus einem Panel, welche für das Zeichnen der Buchsen und Stiften bestimmt ist, und eine Buchse und einen Stift an einer bestimmten Position zeichnet. Die Klassen Stift, EingabeStift, AuswahlStift, Buchse, AntwortBuchse und EingabeBuchse wird Ihnen als Paket ‚view‘ zur Verfügung gestellt. b) Erweitern sie das Spiel, so dass das gesamte Spielbrett beim Aufstarten gezeichnet wird. c) Erweitern sie das Spiel, dass sie einen EingabeStift kreieren können, diesen über das Spielbrett ziehen können und in eine Buchse positionieren können. d) Sobald eine Reihe voll ist, soll mit dem Betätigen des ‚Ok‘-Buttons ein Versuch beantwortet werden, indem die Ausgabe-Stifte gesetzt werden. Seite 18 9. June 2003 Informatik II - Übungen Übung zu Design-Patterns 6 Übung zu Design-Patterns Die im Script vorgestellte Implementierung eines Filesystems wird Ihnen abgegeben. Die Lösung wurde mit dem Composite-Pattern gelöst: Das Traversieren der Datenstruktur erfolgt mit dem Visitor-Pattern. Node _owner _name NodeVisitor 0..* SetName( ) SetOwner( ) Name( ) Owner( ) TraverseRec( ) File _size TraverseRec( ) Size( ) Visit (CFile *) Visit (CDir *) _children PrintVisitor Dir Visit (CFile *) Visit (CDir *) AddNode( ) RemoveNode( ) TraverseRec( ) SizeVisitor _size Visit (CFile *) Visit (CDir *) a) Erweitern Sie das Design, so dass man auch mit einer weiteren Klasse ‚Proxy‘ Verknüpfungen, sogenannte Links (Unix), zu anderen Dateien oder Verzeichnissen erstellen kann, wie z.B. der Link, der auf das Verzeichnis test zeigt. vob dms src magik mmi.magik lme gt test doc user_man.doc Verknüpfung mmi.msg test.lnk b) Programmieren Sie die Klasse ‚Proxy‘ aus und passen Sie das abgegebene Programmsystem an, so dass auch Verknüpfungen möglich sind. Eventuell müssen auch den Visitor anpassen! Seite 19 9. June 2003 Informatik II - Übungen