GUI-Programmierung in Java



Ähnliche Dokumente
Objektorientierte Software-Entwicklung

Java I Vorlesung 11 Graphische Oberflächen mit Swing

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 11/12. Kapitel 7. Grafische Benutzeroberflächen

Zentrale Objekte zur Programmierung graphischer Benutzeroberflächen (GUI)

Graphische Benutzungsoberflächen

GUI Programmierung in Java

GRAFISCHE BENUTZERSCHNITTSTELLEN

Objektorientierte Programmierung

Kap. 35 Swing: Grundlagen Kap Swing: Hauptfenster

Einstieg in die Informatik mit Java

2A Basistechniken: Weitere Aufgaben

Suche schlecht beschriftete Bilder mit Eigenen Abfragen

GUI-Programmierung in Java

Swing Lernen am Code Teil 1

Wichtige Hinweise zu den neuen Orientierungshilfen der Architekten-/Objektplanerverträge

Programmieren in Java

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

GUI Programmierung mit JAVA Swing

Grafische Benutzeroberflächen mit Swing

Benutzeroberflächen. Java Teil 4

Windows 7: Neue Funktionen im praktischen Einsatz - Die neue Taskleiste nutzen

Hochschule der Medien Prof. Uwe Schulz 14. Juli 2010 Klausur Informatik, EDV-Nr Seite 1 von 5. Teil 2: Aufgaben

Objektorientierte Programmierung. Kapitel 12: Interfaces

Eine Anwendung mit InstantRails 1.7

Java: Vererbung. Teil 3: super()

Newsletter. 1 Erzbistum Köln Newsletter

Grundlagen der Programmierung APPLETS

Institut für Programmierung und Reaktive Systeme. GUIs mit Swing. Markus Reschke

Fachbericht zum Thema: Anforderungen an ein Datenbanksystem

Verhindert, dass eine Methode überschrieben wird. public final int holekontostand() {...} public final class Girokonto extends Konto {...

Professionelle Seminare im Bereich MS-Office

Office-Programme starten und beenden

Handbuch zur Anlage von Turnieren auf der NÖEV-Homepage

Erstellen einer Collage. Zuerst ein leeres Dokument erzeugen, auf dem alle anderen Bilder zusammengefügt werden sollen (über [Datei] > [Neu])

Diese Ansicht erhalten Sie nach der erfolgreichen Anmeldung bei Wordpress.

Handbuch ECDL 2003 Modul 2: Computermanagement und Dateiverwaltung Dateien löschen und wiederherstellen

Installation des Authorware Webplayers für den Internet Explorer unter Windows Vista

Einführung in GUI-Programmierung. javax.swing

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

Abteilung Informatik, JFC/Swing 2004 Diego Schmidlin V2.2

Mit der Maus im Menü links auf den Menüpunkt 'Seiten' gehen und auf 'Erstellen klicken.

Kleines Handbuch zur Fotogalerie der Pixel AG

Anleitung zur Verwendung der VVW-Word-Vorlagen

SafeRun-Modus: Die Sichere Umgebung für die Ausführung von Programmen

Über die Internetseite Hier werden unter Download/aktuelle Versionen die verschiedenen Module als zip-dateien bereitgestellt.

Bedienungsanleitung. Matthias Haasler. Version 0.4. für die Arbeit mit der Gemeinde-Homepage der Paulus-Kirchengemeinde Tempelhof

Hilfe zur Urlaubsplanung und Zeiterfassung

1. Allgemein Speichern und Zwischenspeichern des Designs Auswahl der zu bearbeitenden Seite Text ergänzen Textgrösse ändern 3

SICHERN DER FAVORITEN

Outlook. sysplus.ch outlook - mail-grundlagen Seite 1/8. Mail-Grundlagen. Posteingang

Objektorientierte Programmierung

Handbuch für Redakteure

Drei-Schichten-Architektur. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 16: 3-Schichten-Architektur 1 Fachkonzept - GUI

Virtueller Seminarordner Anleitung für die Dozentinnen und Dozenten

Anleitung zur Daten zur Datensicherung und Datenrücksicherung. Datensicherung

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 15/16. Kapitel 7. Grafische Benutzeroberflächen 1

Ereignisbehandlung 21

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom b

3. GLIEDERUNG. Aufgabe:

Handbuch B4000+ Preset Manager

Javakurs für Fortgeschrittene

MORE Profile. Pass- und Lizenzverwaltungssystem. Stand: MORE Projects GmbH

Kapitel 3 Frames Seite 1

Outlook Erstellen einer aus einer HTML - Vorlage INHALT

Stellen Sie bitte den Cursor in die Spalte B2 und rufen die Funktion Sverweis auf. Es öffnet sich folgendes Dialogfenster

Windows. Workshop Internet-Explorer: Arbeiten mit Favoriten, Teil 1

mysql - Clients MySQL - Abfragen eine serverbasierenden Datenbank

5.2 Neue Projekte erstellen

Beschaffung mit. Auszug aus dem Schulungshandbuch: Erste Schritte im UniKat-System

Visio Grundlagen. Linda York. 1. Ausgabe, Oktober 2013

Benutzeranleitung Superadmin Tool

Die Beschreibung bezieht sich auf die Version Dreamweaver 4.0. In der Version MX ist die Sitedefinition leicht geändert worden.

ÖKB Steiermark Schulungsunterlagen

Kostenstellen verwalten. Tipps & Tricks

Software Engineering Klassendiagramme Assoziationen

Design Patterns 2. Model-View-Controller in der Praxis

GEORG.NET Anbindung an Ihr ACTIVE-DIRECTORY

Erstellen von x-y-diagrammen in OpenOffice.calc

Grafikausgabe mit dem Abstract- Windowing-Toolkit. Eine Einführung

HANDBUCH PHOENIX II - DOKUMENTENVERWALTUNG

Abamsoft Finos im Zusammenspiel mit shop to date von DATA BECKER

Tutorial -

Programm GArtenlisten. Computerhinweise

Handbuch ECDL 2003 Basic Modul 2: Computermanagement und Dateiverwaltung Dateien löschen und wiederherstellen

Verwalten und Organisieren von Fotos,

Satzhilfen Publisher Seite Einrichten

SANDBOXIE konfigurieren

DOKUMENTATION VOGELZUCHT 2015 PLUS

Hilfe zur Verwendung digitaler Formulare

Es sollte die MS-DOS Eingabeaufforderung starten. Geben Sie nun den Befehl javac ein.

Navigieren auf dem Desktop

Handbuch für Redakteure

Handbuch ECDL 2003 Basic Modul 6: Präsentation Diagramm auf einer Folie erstellen

Windows 8.1. Grundkurs kompakt. Markus Krimm, Peter Wies 1. Ausgabe, Januar inkl. zusätzlichem Übungsanhang K-W81-G-UA

1. Software installieren 2. Software starten. Hilfe zum Arbeiten mit der DÖHNERT FOTOBUCH Software

Java Projekt: Tic Tac Toe + GUI

Bilder zum Upload verkleinern

Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0)

Transkript:

GUI-Programmierung in Java Von Aydin Alatas und Tobias Fischer Einleitung Im Folgenden wird die Programmierung von Grafikoberflächen in Java erklärt. Diese werden in so gut wie jeder Desktop Anwendung benutzt, weshalb das Thema zu den Grundfähigkeiten eines jeden Programmierers gehören sollte. In unserer Ausarbeitung werden wir nun zuerst die Konzepte für eine sinnvolle und leicht erweiterbare Implementierung von Grafikoberflächen sowie die dafür notwendigen Standardbibliotheken vorstellen. Danach geben wir einen Überblick über die bereitgestellten Komponenten. Ebenso werden wir erläutern, wie man die Komponenten dazu verwendet, die gewünschte Funktion im Programm zu implementieren. Außerdem werden wir zeigen, wie man Parallelität in Bezug auf Grafikoberflächen realisiert und was man dabei beachten muss. Danach erklären wir, wie man mit GUI-Komponenten zeichnen kann und so ihr Aussehen verändert. Zuletzt wenden wir uns in Bezug auf die vorgestellten Programmierkonzepte der Programmlogik zu und erläutern, wie sie mit der Grafikoberfläche interagieren sollte. Als Grundlage haben wir das im Literaturverzeichnis angegebene Handbuch Java ist auch eine Insel von Christian Ullenboom verwendet. Am wichtigsten waren hierbei die Kapitel 14 bzw. 19 in Auflage 9 und Kapitel 14 in Auflage 10. 1.1 Das Model-View-Controller Konzept Das Model-View-Controller (MVC) Konzept ist das zentrale Muster für die Erstellung eines Softwareprojektes mit grafischer Benutzeroberfläche. Erstmals erdacht wurde es um 1978/1979 von Professor Trygve Reenskaug am Xerox PARC und wurde zunächst für Benutzeroberflächen in Smalltalk verwendet. Es besteht aus drei Klassen, die miteinander Interagieren. Zum einen gibt es die sog. View, der die Grafikoberfläche darstellt. Dann gibt es den Controller, der die Benutzereingaben auf dem View registriert und diese an die letzte Klasse das Model, also die Datenverwaltung, weiterleitet. Aufgebaut ist das MVC Konzept auf dem Observer Pattern. Dieses funktioniert wie folgt. Ein Beobachter (ConcreteObserver) meldet sich an und wird über jede Änderung des zu beobachtenden Objekts (Subject) informiert. Dies geschieht über die Methode notifyobservers(). Abbildung 1: Obersever Pattern

Daraus ergibt sich folgender Ablauf: Das Subject registriert eine Änderung und informiert über die Methode notifyobservers() die ConcreteObservers. Überträgt man dies auf das MVC-Konzept, steht das Subject für die View, die eine Änderung z. B. über einen gedrückten Button registriert. Nun wird die Methode notifyobservers() in der Subject Klasse ausgeführt, die den Controller darstellt. Diese informiert die ConcreteObservers, die das Model darstellen, über die Änderung. In dieser Klasse werden dann die konkreten Operationen ausgeführt. Daraus ergibt sich folgende Aufgabenteilung für die Klassen im MVC-Konzept. Abbildung 2: MVC-Konzept Die sog. View repräsentiert die GUI, die den Controller über Benutzereingaben informiert. Dieser ändert die Daten im Model über Methodenaufrufe. Das Model wiederum informiert die View über diese Änderung und die Darstellung wird aktualisiert. Diese Dreiteilung hat den Vorteil, dass alle Komponenten unabhängig entwickelt werden können. Konkret kann man also die View weiterentwickeln, ohne das Model zu beeinflussen. Dies ermöglicht z. B. eine einfache Designänderung von Anwendungsprogrammen. Hat man nun z. B. ein Programm, welches eine Datenbank verwaltet, würde die Datenbank im Model gespeichert werden. Die Oberfläche, auf der die Daten dargestellt werden, wäre die View. Der Controller würde dann z. B. bei einem Klick auf Element löschen dem Model die Anweisung geben, das in der View ausgewählte Element aus seiner Datenbank zu löschen. Das Model würde nun die View über diese Änderung informieren und die View würde die aktualisierten Informationen vom Model einholen und darstellen. 1.2 Modifizierte MVC Architektur für Swing Das MVC-Konzept grenzt die View ganz klar vom Controller ab. Dies ist in der Praxis aber oft nicht sinnvoll. Die Trennung führt nämlich bei den Entwicklern zu einem erhöhten Aufwand, da View und Controller oft eng miteinander verbunden sind und daher bei einer Trennung viele Schnittstellen implementiert werden müssten. Weiterhin ergibt sich dadurch ein erhöhter

Kommunikationsaufwand zwischen den Objekten, da die Benachrichtigung bei Ereignissen in der View immer über den Controller läuft. In unserem Beispiel mit dem Programm zur Datenbankverwaltung müsste nun die View immer den Controller über den Klick auf den Button Element löschen informieren und der Controller müsste sich die Information über das ausgewählte Element bei der View einholen und dann den Befehl an das Model weiterleiten. Diesen Aufwand spart man bei der modifizierten MVC-Architektur. Daher verschmilzt man View und Controller in Swing, um die Interaktion der Objekte zu vereinfachen. Dieses Konzept wird Model View Presenter (MVP-Pattern) genannt. 1.3 Umsetzung von Grafikoberflächen in Java Zur Umsetzung von Anwendungsprogrammen mit Grafikoberflächen stellt Java verschiedene Bibliotheken zur Verfügung. Die zwei wichtigsten sind das oben erwähnte Swing (javax.swing) und das Abstract Window Toolkit, kurz AWT (java.awt). Diese Bibliotheken verfügen über folgende Funktionen: Sie erlauben das Zeichnen grafischer Grundelemente wie Linien und Polygone und ermöglichen das Setzen von Farben und die Auswahl von Zeichensätzen. Sie bieten grafische Komponenten (GUI-Komponenten), auch Steuerelemente oder Widgets genannt, wie zum Beispiel Fenster, Textfelder und Buttons. Sie definieren ein Modell zur Behandlung von Ereignissen, wie etwa Mausbewegungen. AWT war die erste Bibliothek für die Erstellung von grafischen Benutzeroberflächen und ist daher sehr einfach gehalten. Professionelle Oberflächen lassen sich allein mit AWT daher nur mühsam erstellen. Swing erschien drei Jahre später und baut auf AWT auf. Die wesentlichen Unterschiede zwischen Swing und AWT sind: Das AWT bietet weniger Komponenten als Swing. Swing-Komponenten können transparent und beliebig geformt sein; eine Schaltfläche kann abgerundet sein. Jede Swing-Komponente kann mit einem Rahmen versehen werden. AWT-Komponenten arbeiten nicht nach dem MVC-Konzept, die Daten werden also nicht getrennt von der Komponente getrennt gehalten. Die AWT-Methoden sind thread-sicher, es können also mehrere Threads zur gleichen Zeit Methoden der AWT-Komponenten aufrufen. Swing hingegen verzichtet vor allem aus Performance-Gründen auf die Synchronisation der Threads. 2.1 View: Bedienelemente Die Interaktion mit dem Benutzer geschieht in erste Linie mit Bedienelementen. Swing und AWT bieten eine Reihe klassischer Elemente: JButton: Schaltfläche zum Klicken JLabel: Nicht veränderbarer Text JTextField: Beschreibbare Textfläche JList: Liste bestehend aus auswählbaren Elementen

Diese erben alle von der Klasse Component und lassen sich entsprechend in ihrer Beschriftung, Form, Größe etc. manipulieren. Bedienelemente müssen, um angezeigt zu werden, zu sogenannten Containern hinzugefügt werden (siehe nächster Abschnitt). Beispiel: Es soll ein JButton mit dem Standardkonstruktor erstellt werden, welcher einen String entgegennimmt, der die Beschriftung definiert. Er soll die Breite 100px und die Höhe 70px haben. Ebenfalls soll er einen grünen Hintergrund besitzen. Wir verwenden für diese Manipulation die von Component vererbten Methoden setsize(int width, int height) und setbackground(color c). import javax.swing.*; [...] JButton button = new JButton("Button"); button.setsize(100,70); button.setbackground(color.green); [...] 2.2 View: Container Komponenten müssen an einem für den Nutzer sichtbaren und eindeutigen Ort nach ihrer Erstellung angezeigt werden. Hierzu bietet AWT die Klasse Container, welche viele Methoden zur Verwaltung bietet. Dazu gehören Komponenten aufnehmen, nach einem bestimmten Muster anordnen (siehe nächster Abschnitt), anzeigen und nach Belieben wieder entfernen. Auch ist es möglich, einfache Figuren (siehe Abschnitt 3.3 Zeichnen mit GUI-Komponenten ) etc. auszeichnen zu lassen. Das klassische Fenster ist als Klasse JFrame realisiert, welche von Container erbt und in sich selbst noch einige weitere Container abspeichert. Dazu gehört der sogenannte ContentPane, welcher beim Fenster den für die Komponenten gedachten Bereich darstellt. Eine Komponente selbst kann ebenfalls ein Container sein. So gibt es z.b. die Klassen JPanel: Standard-Container JTabbedPane: Mehrere Container, die per Tabs geregelt werden JScrollPane: Container mit Scroll-Funktion JDesktopPane: ermöglicht Fenster-in-Fenster -Funktion, wobei JInternalFrame ein inneres Fenster darstellt Beispiel: Es soll ein Fenster erstellt werden, das einen JButton beinhaltet. Anstatt direkt ein JFrame zu erstellen, erweitern wir es durch eine Unterklasse MyFrame und passen es unseren Bedürfnissen an. Da der Standardkonstruktor von JFrame einen String mit dem Fenstertitel entgegennimmt, rufen wir super(string title) auf. Der zuvor erstellte JButton muss zum ContentPane hinzugefügt werden. Hierzu verwendet man die Methode

JFrame.add(Component c). Damit eine Instanz von MyFrame sichtbar wird, müssen wir anschließend die Methode setvisible(boolean b) mit true aufrufen. import javax.swing.*; class MyFrame extends JFrame{ public MyFrame(String title){ super(title); [...] JButton button = new JButton("Button"); this.add(button); this.setvisible(true); 2.3 View: LayoutManager Damit Komponenten in Containern sinnvoll und vor allem flexibel platziert werden, bieten viele Swing- bzw. AWT-Klassen die Verwendung von LayoutManagern an. Containerklassen wie z.b. das JFrame verteilen ihre Komponenten so, wie es von ihrem LayoutManager bestimmt wird. Dies ermöglicht eine sich der Größe des JFrames dynamisch anpassende Verteilung. So ist es für manche Komponenten sinnvoll, sie unabhängig von der Fenstergröße stets an einen bestimmten Teil mit einer festen Größe anzudocken. Andere sollen vielleicht automatisch zentriert werden und ihre Größe dem Fenster anpassen. Indem man Container innerhalb von Containern verwendet, lassen sich auch Layout-Typen kombinieren, was bei komplexeren Oberflächen oftmals sinnvoll ist. Swing bietet eine Reihe vordefinierter LayoutManager an. Dazu gehören: BorderLayout: Aufteilung in fünf Bereiche (oben, links, zentral, rechts, unten) BoxLayout: horizontale bzw. vertikale absolute Anordnung CardLayout: ermöglicht einfaches anzeigen/verstecken von Containern (ähnlich wie Tabs) FlowLayout: horizontale, zentrierte Anordnung, die sich der Fensterbreite dynamisch anpasst GridLayout: rasterförmige Anordnung, wobei alle Komponenten dieselbe Größe bekommen GridBagLayout: wie GridLayout, jedoch mit beliebiger Größe bzw. Spannweite der Zellen Beispiel: Es sollen ein am oberen Rand angedockter JButton und ein sich dem Fenster anpassende JTextArea erstellt werden. Dafür erscheint die Verwendung des BorderLayouts am sinnvollsten. Dieses muss zunächst erstellt und dem Container (ContentPane) zugewiesen werden. Auf das Layout eines JFrames hat man einfacherweise mit setlayout(layoutmanager lm) Zugriff. Der JButton wird mit dem Parameter BorderLayout.PAGE_START und der JTextArea mit BorderLayout.CENTER zum Container hinzugefügt. Diese Parameter stehen für den oberen und den mittleren Bereich.

import javax.swing.*; import java.awt.*; class MyFrame extends JFrame{ public MyFrame(String title){ super(title); [...] this.setlayout(new BorderLayout()); JButton button = new JButton("Button"); JTextArea textarea = new JTextArea("Text!"); this.add(button, BorderLayout.PAGE_START); this.add(textarea, BorderLayout.CENTER); this.setvisible(true); Abbildung 3: Instanz von MyFrame 3.1 Controller: Event Handling Um den gegebenen Fenstern und Bedienelementen eine bedeutende Funktionalität zuzuschreiben, arbeitet Swing mit sogenannten Ereignisquellen ( event sources ), Ereignissen ( events ) und Horchern ( listeners ). Die Quelle für ein Ereignis kann z.b. ein JButton oder ein JPanel sein. Ein Ereignis selbst ist z.b. das Drücken eines JButtons oder die Veränderung der Größe eines JFrames mit dem Cursor. Jedes dieser Ereignisse führt dazu, dass mind. eine für das Ereignis speziell vordefinierte Methode ausgeführt wird. Standardmäßig ist diese Methode entweder leer (z.b. beim Drücken eines neu erstellten JButtons) oder mit einer intuitiven Funktion versehen (z.b. JFrame Größenanpassung mit Cursor). Diese Methode befindet sich in einem Listener-Objekt, welches zuvor bei der Quelle als Listener angemeldet wurde. Sie bekommt als Parameter ein AWTEvent-Objekt, welches Informationen wie z.b. Quelle und Zeitpunkt des Events bereitstellt. Es können beliebig viele Listener zur Quelle eines Events hinzugefügt werden. Ebenfalls kann ein Listener auf mehrere Events reagieren. Man unterscheidet zwischen mehreren Events, die alle von der Oberklasse AWTEvent erben. Die wohl wichtigsten sind: ActionEvent: z.b. JButton-Klicks oder JRadioButton-Markierung WindowEvent: z.b. Schließen eines JFrames MouseEvent: z.b Maus-Klicks oder einfache Mausbewegungen auf JFrames Nach der Erstellung eines Fensters wird parallel dazu noch eine Ereignisschlange ( event queue ) angelegt und ein sogenannter AWT-Event-Thread ( event dispatch thread ) gestartet. Wenn nun im Fenster Events registriert werden, werden diese als ein AWTEvent-Objekt an die EventQueue des Fensters angehängt und vom AWT-Event-Thread abgearbeitet, indem die jeweiligen Listener- Programmcodes ausgeführt werden. Beispiel:

JButton button1 bzw. button2 sollen bei Betätigung ihre Beschriftung ausgeben. Der JButton-Druck ist ein ActionEvent. Um ein solches Event abzufangen, geht man wie folgt vor: 1) Es muss zunächst ein Objekt erzeugt werden, welches ActionListener und somit die Methode public void actionperformed(actionevent e) implementiert. import java.awt.event.*; class MyActionListener implements ActionListener{ public void actionperformed(actionevent e){ String name = ((JButton)(e.getSource())).getText(); System.out.println(name); Dies kann unter anderem durch die Verwendung anonymer innerer Klassen oder durch Auslagerung in Listener-Klassen realisiert werden. Da in dem Beispiel beide Buttons eine sehr ähnliche Funktion haben sollen, reicht es, nur einen Listener zu erstellen, und diesen für beide Buttons zu verwenden. Für den einzigen Unterschied (also die Beschriftung des Buttons bei der Ausgabe) können wir das mitgegebene Objekt des ActionEvents verwenden, welches den Namen der Quelle mitliefert. Unser ActionListener wird eine Instanz der Klasse MyActionListener. 2) Der erstellte Listener muss nun mit der von JButton bereitgestellten Methode addactionlistener(actionlistener a) bei button1 und button2 angemeldet werden. import javax.swing.*; class MyFrame extends JFrame{ public MyFrame(String title){ super(title); [...] JButton button1 = new JButton("Button1"); JButton button2 = new JButton("Button2"); MyActionListener listener = new MyActionListener(); button1.addactionlistener(listener); button2.addactionlistener(listener); this.add(button1); this.add(button2); this.setvisible(true); Wenn nun ein ActionEvent durch button1 bzw. button2 ausgelöst wird, werden alle ActionListener, die zuvor bei button1 bzw. button2 angemeldet wurden, informiert, indem ihre actionperformed-methoden aufgerufen werden. Entsprechend wird "button1" bzw. "button2" ausgegeben.

In Bezug auf das bereits vorgestellte MVC-Konzept entspricht MyFrame dem View und MyActionListener dem Controller. 3.2 Parallelität und GUI-Komponenten 3.2.1 Threads Bei den meisten Anwendungsprogrammen mit Grafikoberfläche ist es wichtig, dass man mehrere Operationen gleichzeitig ausführen kann. Lädt man mit seinem Programm beispielsweise eine große Datei, soll die Grafikoberfläche dabei nicht einfrieren, sondern es soll z. B. ein Fortschrittsbalken durchlaufen. Um eine solche Parallelität zu realisieren, ist die Verwendung von sog. Threads notwendig. Threads sind Ausführungsstränge innerhalb eines Prozesses, die quasi gleichzeitig ablaufen sollen. Dies wird durch das Betriebssystem gewährleistet, welches alle paar Millisekunden zwischen den vorhandenen Threads umschaltet und so eine verzahnte Bearbeitung der Prozesse gewährleistet. Will man nun einen neuen Thread in sein Programm einbauen, muss die Klasse, die den Thread beinhaltet, das Interface java.lang.runnable implementieren. Dieses besitzt die Methode run(), in der man definiert, was der Thread tun soll. Um den Thread zu starten, ruft man Thread.start() auf. Dazu sehen wir uns folgendes Beispiel an. Hier werden zwei Threads erstellt, die jeweils das Wort Eins bzw. Zwei in der Konsole ausgeben. public class TestThreads{ public static void main(string[] args){ Thread t1 = new Thread(new MyThread("Eins")); Thread t2 = new Thread(new MyThread("Zwei")); t1.start(); t2.start(); class MyThread implements Runnable{ final String mytext; public MyThread(String s){ mytext = s; @Override public void run(){ for(int i = 0; i < 20; i++){ System.out.println(myText); Abbildung 4: Ausgabe der Konsole

Hier sieht man sehr gut die verzahnte Bearbeitung der Threads, wodurch scheinbare Parallelität erzeugt wird. Diese verzahnte Bearbeitung kann allerdings zum Problem werden, wenn zwei Threads auf dieselbe Komponente zugreifen wollen. Hier kann es zu sog. Deadlocks kommen. Deadlocks sind unerwünschte, aber mögliche Programmzustände, in denen zwei Threads sich gegenseitig blockieren und deshalb keiner der beiden Threads weiterarbeiten kann. Diese zu vermeiden ist Aufgabe des Programmierers, da Swing wie in Abschnitt 1.3 erwähnt nicht thread-sicher ist. 3.2.2 Richtiger Umgang mit Threads Die Tatsache, dass Komponenten sowie Model-Daten nicht nur vom AWT-Event-Thread manipuliert werden können, kann zu einigen unerwünschten Zuständen führen. So kann es sein, dass die Datenverwaltung die Benutzeroberfläche über eine Datenänderung informiert und anschließend von einem anderen Thread unterbrochen wird, welcher eine weitere Datenänderung durchführt, noch bevor die Benutzeroberfläche aktualisiert werden konnte. Dies führt dazu, dass die Benutzeroberfläche anschließend auf Basis veralteter Informationen auf die Datenverwaltung zugreift, um nach den neuen Daten zu suchen, und unter Umständen nicht das findet, was sie sucht, was zu Exceptions führen kann. Um solche Unstimmigkeiten zu vermeiden, ist es sinnvoll, Änderungen der Benutzeroberfläche ausschließlich durch den AWT-Event-Thread auszuführen. Da dieser einfach und zuverlässig die EventQueue abarbeitet, herrscht ein gewisser Determinismus, was beim parallelen Arbeiten mehrerer Threads nicht der Fall ist. Die Klasse EventQueue stellt für dieses Problem zwei statische Methoden bereit: 1. invokeandwait(runnable r) nimmt eine Runnable-Implementierung des auszuführenden Codes entgegen, übergibt der EventQueue diesen und wartet, bis der Code vom AWT-Event-Thread ausgeführt wurde 2. invokelater(runnable r) funktioniert genauso wie invokeandwait(...), jedoch wird nicht auf die Ausführung des Codes gewartet, sondern sofort weiter gearbeitet Der AWT-Event-Thread führt die angemeldeten Programmstücke aus, nachdem die EventQueue abgearbeitet wurde. Mit diesen Methoden können andere Threads Änderungen an der Benutzeroberfläche/Daten vornehmen, ohne dass es zu dem oben beschriebenen Problem kommen kann. Beispiel: Es soll ein JProgressBar mit dem Variablennamen pbbar von einem nicht-awt-event-thread auf den Wert x aktualisiert werden. Die Verwendung von invokelater(runnable r) erscheint hier am sinnvollsten, da die Aktualisierung eines Prozessbalkens meist nicht zwingend Voraussetzung für den darauf folgenden Code ist. EventQueue.invokeLater( new Runnable(){ public void run(){ pbbar.setvalue(x); );

3.3 Zeichnen mit GUI-Komponenten GUI-Komponenten besitzen vordefinierte Methoden, die sich wie in jeder Klassenhierarchie überschreiben lassen. So kann man durch das Überschreiben dieser Methoden das Verhalten und die Funktion der GUI-Komponente beliebig anpassen. Im Folgenden wird dies am Beispiel des im Vorführungsprogamm verwendeten DrawPanels veranschaulicht. Hier erstellen wir eine neue Unterklasse von JPanel, das DrawPanel. Nun passen wir die Methode protected void paintcomponent(graphics g) der Oberklasse JPanel so an, dass es möglich wird, auf dem Panel Linien zu zeichnen. Dies geschieht, indem wir auf das Objekt g der Klasse Graphics die bereitgestellte Methode drawline(int x1, int y1, int x2, int y2) ausführen. Das übergebene Graphics-Objekt g ist ein Attribut der Klasse Window, von der JPanel erbt. Es kann auch mit der Methode getgraphics() der Klasse JPanel aufgerufen werden. Dieses Objekt stellt die grafische Darstellung des Panels auf dem JFrame dar. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class DrawPanel extends JPanel{ @Override protected void paintcomponent( Graphics g ) { super.paintcomponent( g ); g.drawline( 10, 10, 100, 50 ); Man führt also nun zuerst die paintcomponent-methode der Klasse JPanel aus, um das Panel auf das JFrame zu zeichnen. Danach wird zusätzlich eine Linie vom Punkt (10,10) zum Punkt (100,50) gezeichnet. Die paintcomponent-methode wird immer dann ausgeführt, wenn man das Panel in seiner Form verändert. Will man nun mit der Maus etwas zeichnen können, muss man dazu einen sog. MouseMotionListener verwenden, der analog zum bereits vorgestellten ActionListener funktioniert. public class DrawPanel extends JPanel { public DrawPanel(){ ); [...] setbackground(color.white); addmousemotionlistener(new MouseMotionAdapter(){ @Override public void mousedragged(mouseevent e){ getgraphics().filloval(e.getx(), e.gety(), 3, 3);

Hier wird nun etwas auf das Panel gezeichnet, wenn man die linke Maustaste gedrückt hält. Dies geschieht mithilfe der Methode mousedragged, die der MouseMotionListener bereitstellt. Hier wird ein ausgefülltes Oval gezeichnet, das eine Höhe und Breite von 3 Pixeln hat und auf der aktuellen Mausposition liegt. Diese Änderungen verfallen allerdings mit erneutem Aufruf der paintcomponent-methode des DrawPanels, da es bei Veränderung seiner Form neu gezeichnet werden muss. Demnach muss man die vorher begangenen Veränderungen speichern und wieder Abrufen. Dies geschieht in der Model Klasse. 4.1 Model: Datenspeicherung In der Model Klasse werden nun, wie in Abschnitt 1.1 beschrieben, die programmrelevanten Daten verwaltet. Dies wird wieder anhand unseres Vorführprogramms erläutert. Hier müssen wir nun die Änderungen, die im DrawPanel registriert werden, speichern. Dies geschieht über eine ArrayList. Hier wird alles Relevante festgehalten und bei einem erneuten Aufruf der paintcomponent-methode abgerufen. Dies sieht dann wie folgt aus: @Override public void paintcomponent(graphics g){ super.paintcomponent(g); for (int i = 0; i < model.data.size(); i++){ paint(g, model.data.get(i)); Die ArrayList data, die aus Objekten der Klasse Figur besteht und in der Klasse model gespeichert wird, enthält alle begangenen Änderungen durch den Nutzer. In der Klasse Figur werden dabei alle relevanten Daten zur gezeichneten Figur gespeichert. Dazu zählen z. B. die Mausposition, der ausgewählte Modus (Viereck, Kreis, Strich, etc.) und die ausgewählte Farbe. Das gesamte Bild besteht dann aus Objekten der Klasse Figur, die mit der Methode paint(graphics g, Figur f) erneut auf das DrawPanel gezeichnet werden. Zusammenfassung Wichtig für die Erstellung eines eigenen Softwareprojektes mit Grafikoberfläche in Java ist nun, immer nach dem MVC-Konzept zu arbeiten. Dies ermöglicht eine separate Entwicklung von Oberfläche und Programmlogik. Weiterhin sollte man die Standardbibliotheken Swing und AWT kennen und die bereitgestellten Komponenten korrekt implementieren können. Außerdem ist die Implementierung der EventHandler sehr wichtig, um der Oberfläche eine Funktionalität zu geben. Darüber hinaus sollte man bei komplexeren Programmen darauf achten, Threads zu verwenden, um einem Einfrieren der Grafikoberfläche vorzubeugen. Hierbei ist besonders darauf zu achten, keine kritischen Zustände durch parallelen Zugriff auf Komponenten zu erzeugen. Außerdem kann man seine Swing Komponenten auch selbst gestalten und in ihrem Aussehen verändern. Dies geht über die vorstellte Methode oder über entsprechende Attribute der Komponenten.

Literaturverzeichnis Ullenboom, Christian: Java ist auch eine Insel. Das umfassende Handbuch, hg. von Rheinwerk Computing, Bonn, 10., aktualisierte Auflage, 2011 Ullenboom, Christian: Java ist auch eine Insel. Das umfassende Handbuch, hg. von Rheinwerk Computing, Bonn, 9., aktualisierte Auflage, 2010 Abbildung 1: WikiSolved: Observer Pattern, Online-Publikation, http://upload.wikimedia.org/wikipedia/commons/thumb/8/8d/observer.svg/500px- Observer.svg.png, Stand: 07.04.2015 Abbildung 2: Stefan Middendorf, Reiner Singer, Jörn Heid: Java. Programmierhandbuch und Referenz, Online-Publikation, https://www.dpunkt.de/java/images/mvc.gif, Stand: 07.04.2015