(1) Softwareentwicklung 2 Universität Paderborn Fachbereich Mathematik/Informatik (17) Sommersemester 2003 Prof. Dr. Stefan Böttcher mit Unterlagen erstellt von Prof. Dr. Gerd Szwillus (2) 0 Einleitung Ziele der Vorlesung: Die Studierenden sollen ihre Kenntnisse in der Programmentwicklung in Java vertiefen lernen, Sprachkonstrukte sinnvoll und mit Verständnis anzuwenden. lernen, Software aus objektorientierten Bibliotheken (z.b. Swing) wiederzuverwenden. grundlegende Konzepte der nebenläufigen Programmierung verstehen und anzuwenden lernen. Erfahrungen im praktischen Arbeiten im Team erwerben. Darauf bauen größere praktische Entwicklungen in Java oder anderen Programmiersprachen während des Studiums und danach auf. Gliederung: 1. Vorbereitung der Programmierung grafischer Oberflächen 2. Programmierung graphischer Benutzungsschnittstellen (mit Swing) 3. Applets 4. Nebenläufigkeit, Threads und Synchronisation
(3) 1 Vorbereitung der Programmierung grafischer Oberflächen 1.1 Verwendung von Konstruktoren Der Default-Konstruktor (=Standard-Konstruktor) ist parameterlos und wird implizit aufgerufen, sofern nicht explizit ein anderer Konstruktor asufgerufen wird. Beispiele dazu in der Vorlesung 1.2 Verwendung von super( ) super(...) ; ruft den Konstruktor der Oberklasse, muß erster Befehl in der Konstruktorimplementierung sein. super() ; wird implizit als erster Befehl im Konstruktor aufgerufen, wenn dort kein anderer Konstruktoraufruf der Oberklasse explizit aufgerufen wird. Idee: Jede (Unter-)Klasse initialisiert die jeweils (zusätzlich) definierten Attribute in ihrem Konstruktor. Beispiel dazu in der Vorlesung 1.3 Verwendung von super.m( ) super.m() ; ruft Methode m() der Oberklasse auf (statt Methode m() der Klasse selbst). Häufig verwendet in Methode einer m(), die die Methode m() der Oberklasse nur geringfügig erweitern will und durch diesen Aufruf die Funktionalität der Methode m() der Oberklasse einbindet. Beispiel dazu in der Vorlesung super.m() verhindert einen rekursiven Aufruf. (4)
(5) 1.4 Benutzung von vordefinierten Java-Klassenbibliotheken Dateistruktur der Dokumentation und Paketstruktur von Java-Bibliotheken Nutzung der Klasse String Warum finde ich System.out.println( string1 ) NICHT in der Klasse String (sondern über die Klassen System und PrintWriter)? Weil entscheidend ist, an welches Objekt println(...) geschickt wird (System.out). Aufbau und Organisation der Java-Dokumentation. Suche von Klassen (z.b. String), Methoden (z.b. compareto(...) ) und Interfaces (z.b. Comparable) in der Java-Dokumentation Bedeutung der Vererbungshierarchie (z.b. Ableitung von der Klasse Object): für einen formalen Parameter Referenz auf eine allgemeinere Klasse (z.b. Referenz auf Objekt) kann man eine Referenz auf eine speziellere Klasse (z.b. Referenz auf String) einsetzen, z.b. um compareto(...) auf Strings anzuwenden. Am Computer demonstrierte Beispiele in der Vorlesung. 1.5 Namenlose (anonyme) Klassen dienen dazu abweichendes Verhalten (hier die show( )-Funktion) zu definieren, das nur an einer Stelle (hier für den Punkt p) benötigt wird. class Punkt double x,y ; Punkt (double xn, double yn)x=xn;y=yn; void show() System.out.println("("+x+","+y+")"); class Test public static void main(string[] args) Punkt p = new Punkt(3,4)void show() System.out.print("(x,y)="); super.show(); ; p.show() ; häufig benutzt in grafischen Oberflächen (z.b. beim Hinzufügen von Routinen zur Ereignisbehandlung). (6)
(7) 2 Programmierung graphischer Benutzungsschnittstellen (mit Swing) Gliederung: Graphische Benutzungsschnittstellen (GUI = Graphical User Interface) Was ist anders in der Benutzung als bei nicht-graphischen Benutzungsschnittstellen? Was ist überhaupt schwierig daran, GUIs zu programmieren? Die Swing-Klassenhierarchie, Verwendung von Bibliotheken Wie ändert sich die Programmstruktur bei GUIs? Abläufe in einer graphischen Benutzungsschnittstelle Verarbeiten von Ereignissen, Umgang mit nebenläufigen Vorgängen Einsatz der Swing-Komponenten Fenster, Buttons, Label, Menüs,... - wie werden sie programmiert? (8) 2.1 Graphische Benutzungsschnittstellen Graphische Benutzungsschnittstellen dienen zur interaktiven Bedienung von Programmen, Ein- und Ausgabe mit graphischen Techniken und visuellen Komponenten Bedienung durch den Benutzer mit Zeigen, Clicken, Draggen, Tippen, Einrahmen,... (WIMP-Interfaces = Windows, Icons, Menus, Pointers) Benutzer löst Ereignisse aus! Ereignisse müssen abgefangen, erkannt, den richtigen Einheiten zugeordnet und von diesen interpretiert werden Ereignisse sind wesentliches Programmierkonzept!
(9) Abkehr von der "readline()-println()"-sichtweise auf die Benutzungsschnittstelle: Bisher: Programm hat volle Kontrolle über den Eingabekanal: public static void main(string [] args) Stream t = new Stream(System.in); System.out.print("Bitte geben Sie Ihren Namen ein: "); String s = t.readline(); System.out.println("Eingelesener Name: "+s);... Dadurch ergibt sich der Ablauf: C:\>java MeinProgramm Bitte geben Sie Ihren Namen ein: Heinrich Eingelesener Name: Heinrich... Nach dem Prompt wartet das Programm, ggf. der gesamt Computer, auf die Eingabe! (10) Jetzt: Einführung der Direkten Manipulation als Grundprinzip Eigene Applikation mit graphischen Bedienelementen Anklicken von Buttons, Bewegen von Elementen in der Zeichenfläche, Menüstrukturen, Fenstermanipulationen, Eintippen von Text,... Eingebettet in ein Fenstersystem! Aber: nicht alleine, sondern nebenläufig vieles gleichzeitig! Die eigene Applikation MS WORD Desktop Die Task-Leiste Ein Zeichenprogramm Bildschirm-Capture-Programm...
(11) (12) Konsequenz: Die eigene Applikation muß zu allem anderen "passen"... Wechsel zwischen Applikationen durch Mausbewegung oder TAB-Taste oder ähnliches Entgegennahme von Tastaturereignissen Wiederherstellen von Bildschirminhalten, wenn Fenster verdeckt und wieder aufgedeckt werden Die eigene Applikation darf nicht alles andere blockieren... nämlich zum Window-Manager. Demgemäß muß sie einiges "können": Ausführung beginnen, unterbrechen, wiederaufnehmen und beenden können, wenn "von oben" verlangt Tastaturereignisse "von oben" entgegennehmen, Kontrolle über Tastaturereignisse wieder "verlieren" "Ihren" Bildschirminhalt neu zeichnen, wenn verlangt Selbst in intensiven Rechenzeiten zwischendurch immer wieder "oben" nachfragen, ob andere "Rechenzeit" brauchen
(13) Javas Standardbibliothek der Swing-Komponenten (bereits integriert in Java 1.3) enthält wiederverwendbare Klassen zur Implementierung und Benutzung der wichtigsten GUI- Komponenten: - Graphik (Kreise, Linien,...) - GUI - "Widgets" (Buttons, Labels, Scrollbars, Windows, Comboboxes, Textfelder,...) - Plazierung, Layoutmanager - Bildmanipulation (skalieren, anpassen,...) - Ereignisbehandlung leistet vor allem aber die Einbindung in die Fensterumgebung der graphischen Bedienoberfläche (Windows, KDE, Mac,...) (14) Entwicklung von Benutzungsschnittstellen ist einerseits ein Softwareproblem (Java, Programmieren)...... aber es ist vor allem (inzwischen) ein interdisziplinäres Entwicklungsproblem Gestaltung von Benutzungsschnittstellen Modellierung von Benutzungsschnittstellen Programmieren von Benutzungsschnittstellen Usability Engineering Programmieren von Websites Web Site Usability Web Applikationen (E-Commerce, B2B Applikationen, Datenbankapplikationen,...) Beteiligt an der industriellen Entwicklung von Benutzungsschnittstellen: Softwareentwickler, Psychologen (kognitive), Usability Engineer, Interface Designer, Anwender, Auftraggeber,...
(15) 2.2 Verwendung der Swing-Klassenhierarchie Genauer: JFC (Java Foundation Classes) unterstützen die Implementation von GUIs - die Swing- Klassen entsprechen den graphischen Komponenten Nachfolger des awt (Abstract Window Toolkit), erweitert dieses in vieler Hinsicht, insbesondere wählbares Look & Feel (Motif, Windows, Java,...) Einbinden von Swing-Komponenten durch import javax.swing.*; Ein erstes Programm: import javax.swing.*; class Swing1 public static void main(string[] args) JFrame frame = new JFrame("Swing-Programm Nummer Eins"); JLabel label = new JLabel("Hello World"); frame.getcontentpane().add(label); Swing1.java frame.setsize(300,100); frame.setvisible(true); (16)
(17) Die Klasse JFrame implementiert gerahmte Fenster in graphischen Benutzungsschnittstellen. Ein JFrame wird auf der Oberfläche als Fenster angezeigt, es hat einen Titel ("Swing-Programm Nummer Eins"), den man beim Erzeugen (Konstruktor), aber auch später mit settitle(..) setzen kann, es hat eine definierte Anfangsgröße (300 breit, 100 hoch, Angabe in Pixel = Bildpunkten des Graphikbildschirms), es wird explizit sichtbar gemacht, es ist eine Container-Klasse - kann also andere Swing-Komponenten aufnehmen (enthalten = to contain) und diese anzeigen, indem man die Swing-Komponente dem ContentPane des Frames hinzufügt. Die Klasse JLabel implementiert eine Textanzeige. Es hat einen Textinhalt, den man beim Erzeugen (Konstruktor), aber auch später mit settext(...) setzen kann. (18) "Fähigkeiten" dieses Programms: Element in der Task-Leiste (Windows), Verschieben, Vergrößern/verkleinern, zum Symbol machen, Wiederherstellen nach Verdecken,...
(19) Wann ist das Programm zu Ende? Klick ins "Kreuz" rechts oben: Fenster zu, Programm läuft noch...! Erst CTRL-C beendet das Java-Programm wirklich. (20) Erzeugen des Frames... meldet ihn beim Fenstersystem an, danach lebt der Frame eigenständig weiter, bis er explizit vom Benutzer durch eine Aktion oder von einem Programm, das auf ihn Zugriff hat, beendet wird Variante A des ersten Programms: Programm wird beendet, wenn Frame geschlossen wird Einfügen der folgenden Zeilen frame.addwindowlistener( new WindowAdapter() public void windowclosing(windowevent e) System.exit(0); // Dieser Aufruf beendet jedes Java-Programm ); Benötigt auch den Import der AWT-Klassen (Vorläufer von Swing): import java.awt.*; import java.awt.event.*; Swing2.java
(21) Grundidee: Einfügen eines Lauschers in den Frame, der das Drücken auf das Schließen -Kreuz abwartet Wenn dieses Ereignis kommt, wird die Methode windowclosing() ausgeführt Diese Methode wird für unseren Frame so überschrieben, daß System.exit(0); ausgeführt wird. Variante B: Erzeugen vieler Label Grundidee: Statt eines Label 10 Stück erzeugen, alle dem contentpane des Frames hinzufügen, das Ganze anzeigen, Kontrollausdruck mit System.out.println(...) for (int i=0; i < 10; i++) frame.getcontentpane().add(new JLabel("Label "+(i+1))); System.out.println("Label "+(i+1)+" erzeugt."); Ergebnis: Nur Label 10 ist zu sehen...?!?!? Fehler : Standardmäßig wird jede neue Komponente in die Mitte des contentpane plaziert ( BorderLayout.CENTER ) Lösung: Umschalten auf FlowLayout - dann werden alle Komponenten nacheinander von links oben nach rechts unten einkopiert: (22) frame.getcontentpane().setlayout (new FlowLayout()); Swing3.java Ergebnis
(23) Variante C: Definition eines eigenen Fenstertyps ( MyFrame ) Unterklasse von JFrame Erzeugen zweier Fenster dieses Typs mit verschiedenen Titel In den Fenstern jeweils wie vorher 10 Labels Alle definierenden Aktionen des Fenstertyps im Konstruktor von MyFrame Im Hauptprogramm: Erzeugen zweier Objekte vom Typ MyFrame public static void main(string[] args) new MyFrame("Erstes Fenster"); new MyFrame("Zweites Fenster"); Optisches Ergebnis Abbruch des Programms bei jedem der beiden Fenster! (24)
(25) class MyFrame extends JFrame MyFrame(String s) super(s); getcontentpane().setlayout(new FlowLayout()); Swing4.java for (int i=0; i < 10; i++) getcontentpane().add(new JLabel("Label "+(i+1))); System.out.println("Label "+(i+1)+" erzeugt."); setsize(300,300); setvisible(true); addwindowlistener( new WindowAdapter() public void windowclosing(windowevent e) System.exit(0); ); (26) Variante D: Zeichnen in das Fenster Wieder: Definition eines eigenen Fenstertyps Überschreiben der fenstereigenen paint-methode mit einer eigenen Zeichenroutine class MyFrame extends JFrame MyFrame(String s)... // wie vorher Swing5.java public void paint(graphics g) g.drawline(0,0,300,300); g.drawline(300,0,0,300);
(27) Erzeugen zweier Fenster dieser Art liefert (28) JFrame ist Blattknoten in der Swing-Klassenhierarchie Ausschnitt aus der Webseite im Java-Sun-Swing-Tutorial http://java.sun.com/j2se/1.4/docs/api/javax/swing/jframe.html
(29) Verschiedene Eigenschaften sind auf verschiedenen Ebenen der Vererbungshierarchie untergebracht: JFrame (swing) - Erweiterung der (älteren) Frame-Klasse des awt, die Frames in die JFC-Umgebung einbindet Frame (awt) - Fenster mit Rand, Titel, Menüleiste, veränderbarer Größe Window (awt) - Fenster ohne Rand Container (awt) - Komponenten, die wieder andere Komponenten aufnehmen können Component (awt) - die eigentlichen GUI-Elemente (Widgets) Object (lang) - die allgemeinste Java-Klasse Viel (auswendig) zu lernen, bzw. viel Sucharbeit in Dokumentationen, optimal parallel geöffnetes Browserfenster nach: http://java.sun.com/j2se/1.4/docs/api/overview-summary.html Von dort Verzweigen zu allen vorhandenen Packages - genaue Klassenbeschreibung, Hierarchie, Methoden, Variablen,... (30) Ausschnitt aus der Hierarchie der GUI-Komponenten: Component (abstract) darstellbare Komponenten von Benutzungsoberflächen Container (abstract) Behälter für Komponenten Panel konkrete Klasse zu Container, Behälter für Komponenten ScrollPane Sicht auf große Komponente, 2 Rollbalken Window Fenster (ohne Rand, Titel, usw.) Dialog Fenster; fordert interaktive Bearbeitung FileDialog Fenster zur interaktiven Dateiauswahl Frame Fenster mit Rand, Titel, Menüleiste; veränderbare Größe Button Schaltknopf Canvas frei verwendbare rechteckige Zeichenfläche CheckBox An/Aus-Schalter Choice Auswahl aus einer Liste von Texten (ausklappbar) List Auswahl aus einer Liste von Texten (mit Rollbalken) Scrollbar Rollbalken zur Einstellung eines ganzzahligen Wertes Label Textzeile TextComponent editierbarer Text TextField einzelne Textzeile TextArea mehrzeiliger Text mit Rollbalken
(31) Optisch: (32) Alle Informationen von der Sun-Website http://java.sun.com/docs/books/tutorial/uiswing/components/components.html