Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5...

75
1 FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK BEREICH DATENTECHNIK V JV 500 00 TH 01 ----------------------------------------------------------------------------------- Programmieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes Überblick 5.3 Basisklassen der JFC-Hierarchie 5.4 Erstellung einer GUI-Anwendung 5.5 Beeinflussung des Erscheinungsbildes 5.6 Ausgewählte Swing-Komponenten-Klassen 5.7 Ereignisverarbeitung 5.8 Entwurfsmuster mit GUI-Bezug Stand 05.10.2013

Transcript of Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5...

Page 1: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

1

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 500 – 00 – TH – 01

-----------------------------------------------------------------------------------

Programmieren in Java

Kapitel 5

5. Graphische Benutzeroberflächen 5.1 Grundprinzip

5.2 Java Foundation Classes – Überblick

5.3 Basisklassen der JFC-Hierarchie

5.4 Erstellung einer GUI-Anwendung

5.5 Beeinflussung des Erscheinungsbildes

5.6 Ausgewählte Swing-Komponenten-Klassen

5.7 Ereignisverarbeitung

5.8 Entwurfsmuster mit GUI-Bezug

Stand 05.10.2013

Page 2: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

2

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 511 – 00 – TH – 02

-----------------------------------------------------------------------------------

Grundprinzip graphischer Benutzeroberflächen

Aufbau graphischer Benutzeroberflächen

◇ Eine graphische Benutzeroberfläche (Graphical User Interface, GUI) ist typischerweise aus hierarchisch strukturier-

ten Komponenten aufgebaut.

◇ Die einzelnen GUI-Komponenten – auch controls oder widgets ( = window gadgets) genannt – erfüllen jeweils spezielle

Aufgaben. Die meisten von ihnen ermöglichen es dem Benutzer, durch Eingaben mittels Maus, Tastatur oder einem

anderen Eingabegerät mit Ihnen und damit mit dem Programm zu interagieren.

◇ Die hierarchische Struktur einer graphischen Benutzeroberfläche ergibt sich dadurch, dass einige GUI-Komponenten,

Container genannt, andere Komponenten enthalten können.

An der "Spitze" jeder graphischen Benutzeroberfläche steht ein sogenannter Top-Level-Container. Die in ihm enthal-

tenen Komponenten können "elementare" Komponenten oder wiederum Container sein, welche dann weitere Kom-

ponenten enthalten können, usw.

Eine an einen Container gerichtete Aufgabe (z.B. paint(), "zeichne Dich") führt dieser für sich – soweit zutreffend – aus

und delegiert dann die weitere Ausführung an alle in ihm enthaltenen Komponenten.

Eine derartige Struktur führt programmtechnisch zu einer Implementierung des Entwurfsmusters Composite.

◇ Beispiele für elementare GUI-Komponenten :

▪ Beschriftung (Label)

▪ Textfeld (Text Field)

▪ Schaltfläche (Button)

▪ Auswahlfeld (Check Box)

▪ Auswahlliste (List, Combo Box)

▪ Menue (Menu)

◇ Beispiele für GUI-Container

▪ Fenster mit Rahmen (Frame)

▪ Dialogbox (Dialog Box)

▪ Menueleiste (Menu Bar)

▪ Werkzeugleiste (Tool Bar)

▪ Gruppierungsfeld (Panel)

◇ Beispiel : Rahmenfenster (Frame) mit Schaltfläche (Button) und Beschriftung (Label)

Interaktion mit dem Benutzer

◇ Die Interaktion mit dem Benutzer erfolgt ereignisgesteuert.

Jede auf eine GUI-Komponente fallende Benutzereingabe (Mausklick, Mausbewegung, Tastatureingabe, Auswahl aus

einem Menu usw) wird als Ereignis bezeichnet.

◇ Für jede Komponente kann festgelegt werden, auf welches Ereignis wie reagiert werden soll.

◇ Beim Eintritt eines Ereignisses wird die für die betreffende Komponente registrierte Reaktion ausgeführt.

Page 3: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

3

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 521 – 00 – TH – 03

-----------------------------------------------------------------------------------

Java Foundation Classes – Überblick (1)

Bestandteile der Java Foundation Classes (JFC)

◇ Mit den JFC stellt Java eine breites Spektrum von Bibliotheks-Klassen zur Realisierung graphischer Funktionalität

und zum Aufbau von GUIs zur Verfügung.

◇ Die für die Anwendung in GUIs wichtigsten Klassen lassen sich im wesentlichen in die folgenden Gruppen einteilen :

▻ Klassen für elementare GUI-Komponenten

▻ Klassen für GUI-Container

▻ Klassen zur Gestaltung der GUI-Komponenten (Layout-Manager, Farben und Fonts)

▻ Klassen und Interfaces zur Ereignisverarbeitung (Listener, Adapter und Events)

◇ Die JFC umfassen im wesentlichen zwei – sich teilweise ersetzende und teilweise ergänzende – Frameworks :

▻ Abstract Windows Toolkit (AWT) Package java.awt mit mehreren Unterpaketen

▻ Die Swing-Klassen Package javax.swing mit mehreren Unterpaketen

◇ Zusätzlich gehören zu den JFC :

▻ Java 2D API (Klassen zur Realisierung fortgeschrittener 2D-Graphik, Bild- und Textbearbeitung sowie Drucken)

▻ Accessibility API (Klassen zur Realisierung von Interfaces für Behinderte)

▻ Klassen zur Unterstützung international einsetzbarer GUI-Applikationen, die sich leicht an die jeweilige Landes-

sprache und nationalen Konventionen anpassen. Hierzu gehört u.a. das Input Method Framework API.

Abstract Windows Toolkit (AWT)

◇ Ursprüngliches GUI-Paket in Java. Seit dem JDK 1.0 enthalten

Im JDK 1.1. wesentlich überarbeitet, insbesondere bezüglich der Ereignis-Bearbeitung

◇ Bildet auch die Grundlage für das spätere Swing-Paket.

◇ Die Implementierung der AWT-Klassen für die GUI-Komponenten verwendet die durch die Graphik-und Window-

Funktionalität des jeweiligen Betriebssystems zur Verfügung gestellten Komponenten ("heavyweight" components).

Das bedeutet,

- dass nur solche Funktionalitäten implementiert werden konnten, die auf allen wichtigen Plattformen, die Java

unterstützten, existierten ("kleinster gemeinsamer Nenner")

- dass das Aussehen und die Bedienbarkeit ("Look and Feel", LaF) einer graphischen Benutzeroberfläche jeweils

systemspezifisch ist. Die einzelnen GUI-Komponenten werden in der durch das jeweilige Betriebssystems vorge-

gebenen Art und Weise dargestellt.

Die Swing -Klassen

◇ Framework zur Erstellung von GUI-Anwendungen mit erweiterter Funktionalität.

Beim JDK 1.1 als Add-On verfügbar, seit dem JDK 1.2 fester Bestandteil der Java 2 Platform.

◇ Die Swing-Klassen bauen auf dem AWT auf, nutzen vieler seiner Grundfunktionalitäten, u.a. das Model und die

Klassen für die Ereignisbearbeitung, sowie die Klassen zur Gestaltung der GUI-Komponenten.

◇ Die Implementierung der Klassen für die GUI-Komponenten – ausser den Top-Level-Containern – greift nicht mehr auf

die Komponentendarstellung des Betriebssystems zurück. Sie ist vielmehr – unter Verwendung graphischer Primitiv-

Operationen ("lightweight components") vollkommen in Java realisiert. Das bedeutet, das das "Look and Feel" einer mit

Swing-Komponenten realisierten GUI unabhängig vom jeweiligen Betriebssystem und damit für alle Systeme gleich

ist.

◇ Andererseits kann der Programmierer und gegebenenfalls auch der Programmbenutzer das LaF einer GUI-Anwendung

selbst festlegen (Pluggable Look and Feel), wobei zwischen einigen Standard-LaFs ausgewählt werden aber auch ein

eigenes LaF gestaltet werden kann. Es ist sogar möglich das LaF dynamisch während des Programmlaufs zu verän-

dern. Defaultmäßig ist für alle GUI-Komponenten ein Java Look and Feel (Name "Metal") eingestellt.

◇ AWT- und Swing-Klassen für GUI-Komponenten dürfen nicht miteinander gemischt verwendet werden.

Page 4: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

4

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 522 – 00 – TH – 03

------------------------------------------------------------------------------------

Java Foundation Classes – Überblick (2)

Hierarchie der JFC-Klassen für GUI-Komponenten (unvollständig)

MenuComponent

MenuItem

MenuBar

Menu

CheckBoxMenuItem

PopupMenu

AWT Swing Component

Container

Label

Button

Checkbox

… weitere AWT- Komponenten

Panel

Window

ScrollPane

JComponent

Applet

JApplet

Dialog

Frame

JWindow

JDialog

JFrame

FileDialog

JPanel

JComboBox

JMenuBar

JList

Box

JTable

JScrollPane

JPopupMenu

JToolBar

. . .

. . .

. . .

AbstractButton

JTextComponent

JButton

JToggleButton

JCheckBox

JRadioButton

JMenuItem

JTextArea

JTextField

JEditorPane

JMenu

JCheckBoxMenuItem

JPasswordField

… weitere Swing- Komponenten

JTextPane

JRadioButtonMenuItem

. . .

JLabel

Box.Filler

Page 5: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

5

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 523 – 00 – TH – 03

------------------------------------------------------------------------------------

Java Foundation Classes – Überblick (3)

Top-Level-Container

Elementare Komponenten (Auswahl)

"Innere" Container (Auswahl)

AWT Swing Fenster mit Rahmen und Titelleiste Frame JFrame Fenster ohne Rahmen und Titelleiste Window JWindow Dialog-Box Dialog JDialog Applet Applet JApplet

AWT Swing Beschriftung Label JLabel Zeichenfläche Canvas Schaltknopf Button JButton Umschaltknopf (Schaltknopf mit zwei Zuständen) JToggleButton Auswahlfeld Checkbox JCheckBox Gruppe alternativer Auswahlfelder Checkbox JRadioButton

(nur ein Feld kann ausgewählt werden) in Verbindung mit in Verbindung mit CheckboxGroup ButtonGroup Auswahlliste List JList aufklappbare Auswahlliste Choice JComboBox einzeiliges Textfeld (editierbar) TextField JTextField mehrzeiliges Textfeld (editierbar) TextArea JTextArea Bildlaufleiste Scrollbar JScrollBar Bildlauffläche (horizontale u. vertikale Bildlaufleiste) ScrollPane JScrollPane Tabelle JTable Menüeintrag MenuItem JMenuItem

AWT Swing Gruppierungsfeld Panel JPanel Gruppierungbox (festliegender Layout-Manager) Box Menüleiste MenuBar JMenuBar Menu Menu JMenu Werkzeugleiste JToolBar

Page 6: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

6

FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 524 – 00 – TH – 03

-----------------------------------------------------------------------------------

Java Foundation Classes – Überblick (4)

Einige Swing-Komponenten (Java Look and Feel) (Klasse SwingCompDemo)

Page 7: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

7

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 531 – 00 – TH – 04

------------------------------------------------------------------------------------

Basisklassen der JFC-Hierachie (1)

Die abstrakte Klasse Component

◇ Diese – im Package java.awt enthaltene – Klasse steht an der Spitze der Hierarchie der GUI-Komponenten-

Klassen.

Sie definiert grundlegende Methoden, die in fast allen AWT- und Swing-Komponenten-Klassen zur Verfügung

stehen.

Lediglich die AWT-Klassen für Menü-Komponenten befinden sich in einer hiervon unabhängigen Klassen-Hierarchie.

◇ Einige wesentliche Methoden :

(die Methoden zum Registrieren von Listener-Objekten für die Event-Behandlung sind nicht mit aufgeführt )

public void setBackground(Color c) Setzen der Hintergrund-Farbe auf c

public void setForeground(Color c) Setzen der Vordergrund-Farbe auf c

public void setFont(Font f) Setzen der in der Komponente verwendeten Schriftart

public void setSize(int w, int h) Setzen der Breite (auf w) und Höhe (auf h) der Komponente

(Angabe in Pixel)

public void setLocation(int x, int y) Setzen der Position der Komponente

(linke obere Ecke auf (x,y), Angabe in Pixel)

public void setVisible(boolean b) Anzeigen / Verbergen der Komponente

(b==true : Komponente sichtbar, sonst unsichtbar)

public void setEnabled(boolean b) Aktivierung / Deaktivierung der Reaktion der Komponente auf

Benutzereingaben (b==true : Komponente kann auf

Benutzereingaben reagieren (Events erzeugen))

Defaultmässig sind alle Komponenten aktiviert

public Color getBackground() Rückgabe der Hintergrund-Farbe

public Color getForeground() Rückgabe der Vordergrund-Farbe

public Font getFont() Rückgabe der verwendeten Schriftart

public int getWidth() Rückgabe der aktuellen Breite der Komponente (in Pixel)

public int getHeight() Rückgabe der aktuellen Höhe der Komponente (in Pixel)

public boolean isVisable() Rückgabe des Sichtbarkeits-Status der Komponente

true, wenn Komponente sichtbar, false, wenn nicht

public boolean isEnabled() Rückgabe des Aktivierungs-Status der Komponente

true, wenn Komponente aktiviert, false, wenn nicht

public void paint(Graphics g) Zeichnen der Komponente unter Verwendung des Graphik-

Context-Objekts g.

Wird vom System aufgerufen (Callback), z.B. wenn die Kom-

ponente erstmals sichtbar gemacht wird oder eine Zustands-

(z.B. Größen-) änderung erfolgt ist

public void repaint() Aufforderung an das System, die Komponente neu zu zeichnen

(mittels paint())

Kann vom Anwender-Code aufgerufen werden, wenn sich der

Zustand des GUI-Objekts geändert hat.

public void validate() Sicherstellung, dass die Komponente ein gültiges Layout hat

(Diese Methode ist insbesondere für Container vorgesehen)

public void requestFocusInWindow() Anforderung des Focus (wenn Top-Level-Cont. Focus besitzt )

Page 8: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

8

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 532 – 00 – TH – 03

------------------------------------------------------------------------------------

Basisklassen der JFC-Hierachie (2)

Die Klasse Container

◇ Diese – im Package java.awt definierte – Klasse ist die Basisklasse aller GUI-Container-Klassen.

Auch die Klassen für einfache Swing-Komponenten sind – indirekt – von dieser Klasse abgeleitet.

Sie ist selbst von der Klasse Component abgeleitet.

◇ Sie stellt – über die von Component geerbten und teilweise überschriebenen Methoden hinaus – insbesondere

Methoden zur Verfügung, die das Verwalten (z.B. Einfügen, Entfernen) von GUI-Komponenten ermöglichen.

◇ Die in einem GUI-Container-Objekt enthaltenen GUI-Komponenten werden in einer Liste verwaltet, wobei die Reihen-

folge der Listenelemente standardmässig durch die Reihenfolge ihres Einfügens festgelegt ist.

Diese Reihenfolge bestimmt auch die Anordnungs-Reihenfolge der Komponenten entsprechend des jeweils festgeleg-

ten Layout-Managers.

Es ist aber auch möglich, die Reihenfolge der Komponenten (Position bezüglich des gewählten Layouts) durch einen

entsprechenden Parameter ("Index") der Einfüge-Methode explizit zu beeinflussen.

◇ Wenn in einen Container eine Komponente neu eingefügt oder entfernt wird, nachdem der Container bereits sichtbar

ist, muß die von Component geerbte – aber überschriebene – Methode validate() aufgerufen werden.

Dadurch wird der Layout-Manager des Containers veranlasst, das Layout entsprechend anzupassen.

◇ Die von Component geerbte Methode paint() ist so überschrieben, dass für alle im Container enthaltenen

Komponenten deren paint()-Methode aufgerufen wird.

◇ Die wichtigsten Methoden zur Komponentenverwaltung sind :

(die Methoden zum Registrieren von Listener-Objekten für die Event-Behandlung sind nicht mit aufgeführt )

◇ Ein Container besitzt Randbereiche (insets), die nicht für die Aufnahme von Komponenten zur Verfügung stehen

(z.B. die Titelleiste).

Die Randbereiche werden in einem Objekt der Klasse Insets (Package java.awt) zusammengefasst.

Die 4 Randbereiche (Angabe in Pixel) sind zugänglich über public-int-Datenkomponenten : top, left, bottom, right.

Zur Ermittlung des Insets-Objekt eines Containers dient die Memberfunktion :

public Insets getInsets() Ermittlung der Randbereiche des Containers

public Component add(Component comp) Einfügen der Komponente comp am Ende des Containers

public Component add(Component comp, Einfügen der Komponente comp an der Position idx int idx)

public Component add(Component comp, Einfügen der Komponente comp unter Berücksichtigung

Object constr) der durch constr festgelegten Einschränkungen

public Component getComponent(int idx) Ermitteln der Komponente an der Position idx

public Component[] getComponents() Ermitteln aller Komponenten des Containers

public int getComponentCount() Ermitteln der Anzahl der Komponenten im Container

public void remove(Component comp) Entfernen der Komponente comp aus dem Container

public void remove(int idx) Entfernen der Komponente an der Position idx

public void removeAll() Entfernen aller Komponenten aus dem Container

public void setLayout(LayoutManager mgr) Setzen des Layout-Managers mgr für den Container

public LayoutManager getLayout() Ermitteln des Layout-Managers des Containers

Page 9: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

9

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 533 – 00 – TH – 03

-----------------------------------------------------------------------------------

Basisklassen der JFC-Hierachie (3)

Die abstrakte Klasse JComponent

◇ Diese von Container abgeleitete und im Package javax.swing enthaltene Klasse ist Basisklasse aller

Swing-Komponenten-Klassen mit Ausnahme der Top-Level-Container

◇ Die Klasse passt einige der von Container und Component geerbten Methoden an die Funktionalität und

die speziellen Eigenschaften des Swing-Frameworks an.

Zusätzlich definiert sie Methoden, die speziell für Swing-Komponenten von Bedeutung sind

◇ U.a. besitzen Swing-Komponenten die folgenden bei AWT-Komponenten nicht vorhandenen Besonderheiten :

▻ Swing-Komponenten können mit einer Umrandung versehen werden.

Die Umrandung wird durch ein Objekt einer das Interface Border implementierenden Klasse festgelegt.

Zur Erzeugung derartiger Border-Objekte stehen statische Methoden der Klasse BorderFactory zur

Verfügung.

▻ Der Hintergrund von Swing-Komponenten kann durchsichtig (nicht-opak) oder undurchsichtig (opak) sein.

AWT-Komponenten besitzen immer einen undurchsichtigen Hintergrund.

In der Klasse JComponent ist als Default durchsichtig (nicht-opak) festgelegt.

Allerdings hängt der tatsächliche Defaultwert dieser Eigenschaft bei den abgeleiteten Swing-Klassen i.a. von

dem jeweils eingesetzten LaF ab.

▻ Swing-Komponenten können mit einem Tooltip ausgestattet werden. Hierbei handelt es sich um einen mit der

Komponente verknüpften Hinweistext, der angezeigt wird, wenn der Mauszeiger für kurze Zeit über der Kom-

ponente verweilt.

▻ Für Swing-Komponenten können die dem Layout-Manager als Dimensionierungsvorschläge dienenden Werte

für die maximale, die minimale und die bevorzugte Größe (Breite und Höhe) der Komponente sowie Vorschläge

für die Ausrichtung einer Komponente (in x- und y-Richtung) explizit gesetzt werden. Die entsprechenden Ermitt-

lungs-Methoden (get...(), z.B. getMaximumSize()) sind bereits in der Klasse Component definiert.

◇ Zu den wichtigsten der speziellen Swing-Komponenten-Methoden gehören :

(die Methoden zum Registrieren von Listener-Objekten für die Event-Behandlung sind nicht mit aufgeführt )

public void setBorder(Border bord) Setzen des Border-Objekts bord als Umrandung für

die Komponente

public Border getBorder() Ermitteln der Umrandung der Komponente

public void setOpaque(boolean opa) Setzen des Hintergrunds der Komponente auf undurch-

sichtig (opa==true) bzw durchsichtig (opa==false)

public boolean isOpaque() Ermitteln, ob Hintergrund der Komponente undurchsichtig

oder durchsichtig ist

true, wenn undurchsichtig, false, wenn durchsichtig

public void setToolTipText(String txt) Setzen des Tooltip-Textes für die Komponente

public String getToolTipText() Ermitteln des Tooltip-Textes der Komponente

public void setMaximumSize(Dimension d) Setzen der maximalen Größe der Komponente auf die

durch d gegebene Breite und Höhe.

Erzeugung eines Dimension-Objekts : new Dimension(breite, hoehe)

public void setMinimumSize(Dimension d) Setzen der minimalen Größe der Komponente auf d

public void setPreferredSize(Dimension d) Setzen der bevorzugten Größe der Komponente auf d

public void setAlignmentX(float align) Setzen der Ausrichtung in hor. Richtung (0.0 ... 1.0)

public void setAlignmentY(float align) Setzen der Ausrichtung in vert. Richtung (0.0 ... 1.0)

Page 10: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

10

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 541 – 00 – TH – 04

------------------------------------------------------------------------------------

Erstellung einer GUI-Anwendung in Java (1)

Prinzipielle Vorgehensweise

◇ Jede GUI-Anwendung besitzt wenigstens ein Top-Level-Fenster, über das sie mit dem Anwender kommuniziert.

Eine GUI-Anwendung kann auch mehrere Top-Level-Fenster besitzen.

◇ Für jedes Top-Level-Fenster wird eine eigene Klasse definiert.

Der Aufbau dieser Fenster-Erzeugungs-Klasse kann unterschiedlich sein.

Neben anderen bieten sich folgende Hauptvarianten an :

▻ Die Klasse instanziert ein Objekt der eingesetzten JFC-Top-Level-Container-Klasse (i.a. in ihrem Konstruktor)

Dieses kann sie gegebenenfalls über eine Datenkomponente referieren.("has a container")

▻ Die Klasse ist von der eingesetzten JFC-Top-Level-Container-Klasse abgeleitet.

Bei der Instanzierung der Klasse wird das Top-Level-Container-Objekt als Teilobjekt angelegt ("is a container").

◇ Für normale Anwendungsprogramme werden als Top-Level-Container-Klassen i.a. die Klassen Frame (für AWT-

Anwendungen) bzw JFrame (für Swing-Anwendungen) eingesetzt.

◇ Die Konfigurierung eines Top-Level-Fensters und damit der graphischen Oberfläche erfolgt typischerweise im

Konstruktor der Fenster-Erzeugungs-Klasse bzw in speziellen von diesem aufgerufenen Memberfunktionen :

▻ Gegebenenfalls explizite Erzeugung des Top-Level-Container-Objekts (s. oben)

▻ Festlegung des Erscheinungsbildes (ohne LaF, das wird i.a. von ausserhalb , z.B in der main()-Methode der

Start-Klasse, festgelegt) :

▹ Setzen des Layout-Managers (wenn anders als Default)

▹ Setzen der Hintergrund- und Vordergrundfarbe (wenn anders als Default)

▹ Setzen der Schriftart (wenn überhaupt benötigt und anders als Default)

▹ Setzen der (Ausgangs-)Größe des Fensters

Wenn die Fenster-Erzeugungs-Klasse von der Top-Level-Container-Klasse abgeleitet ist, wird das auch

häufig von ausserhalb – nach der Instanziierung der Klasse – vorgenommen.

▹ Setzen des Titels des Fensters

Dieser kann entweder dem Konstruktor der Klasse Frame bzw JFrame übergeben werden oder

mittels der Memberfunktion setTitle() festgelegt werden.

Auch dies erfolgt häufig von ausserhalb des Konstruktors der Fenster-Erzeugungs-Klasse, wenn diese von der

Top-Level-Container-Klasse abgeleitet ist.

▻ Erzeugen, Konfigurieren und Einfügen der Komponenten-Objekte des Containers.

Dies wird sinnvollerweise haeufig in eine eigene Methode ausgelagert.

Zur Konfigurierung einer einzufügenden GUI-Komponente sind gegebenenfalls analoge Schritte wie bei der

Konfigurierung des Top-Level-Fensters auszuführen.

Je nach Komponente stehen u.U. noch zusätzliche Konfigurationsmöglichkeiten zur Verfügung (z. B. Setzen

einer Umrandung) Anmerkung zum Einfügen der Komponenten:

In die AWT-Top-Level-Container (Frame, Dialog, Window) werden Komponenten direkt eingefügt

(mittels add()).

In die Swing-Top-Level-Container ( JFrame, JDialog, JWindow) dagegen werden die Komponenten

nicht direkt eingefügt. Sie verfügen über einen speziellen Einfüge-Container, die sogenannte content pane, in die

alle aufzunehmenden Komponenten mittels add() einzufügen sind.

◇ Definition von Event-Listener-Klassen und Registrierung der Event-Listener-Objekte bei den einzelnen

Komponenten. Dies wird ebenfalls sinnvollerweise haeufig in eine eigene Methode ausgelagert.

Die Kommunikation mit dem Anwender und dem Rest des Anwendungsprogramms (Entity-Klassen) erfolgt nur

über die durch die Event-Listener definierten Methoden (Callbacks !)

◇ Anzeigen des Top-Level-Containers (und aller in ihm enthaltenen Komponenten).

Dies erfolgt durch Einschalten der Sichtbarkeit des Containers (Aufruf von setVisible(true)).

Dies kann entweder ebenfalls im Konstruktor der Fenster-Erzeugungs-Klasse oder – wenn diese von der Top-Level-

Container-Klasse abgeleitet ist – von ausserhalb erfolgen.

Page 11: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

11

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 542 – 00 – TH – 01

-----------------------------------------------------------------------------------

Erstellung einer GUI-Anwendung in Java (2)

Beispiel einer sehr einfachen AWT-Anwendung

Top-Level-Fenster (abgeleitet von Frame) mit einer Label-Komponente

// AWTSimpleFrame.java

import java.awt.*;

public class AWTSimpleFrame extends Frame

{

public AWTSimpleFrame(String title)

{

super(title);

Label lab1 = new Label("Hallo !", Label.CENTER);

add(lab1);

addWindowListener(new WindowClosingAdapter()); // Registrierung eines

// Event-Listeners

// zum Schliessen des Fensters

setSize(300,160);

}

public static void main(String[] args)

{

AWTSimpleFrame fenster = new AWTSimpleFrame("Ein sehr einfaches AWT-Fenster");

fenster.setVisible(true);

}

}

Page 12: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

12

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 543 – 00 – TH – 01

-----------------------------------------------------------------------------------

Erstellung einer GUI-Anwendung in Java (3)

Beispiel einer sehr einfachen Swing-Anwendung

Top-Level-Fenster (abgeleitet von JFrame) mit einer JLabel-Komponente

// SwingSimpleFrame.java

import javax.swing.*;

import java.awt.*;

public class SwingSimpleFrame extends JFrame

{

private Container c;

public SwingSimpleFrame(String title)

{

super(title);

JLabel lab1 = new JLabel("Hallo !", SwingConstants.CENTER);

c = getContentPane();

c.add(lab1);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setSize(320, 160);

}

public static void main(String[] args)

{

SwingSimpleFrame fenster = new SwingSimpleFrame(

"Ein sehr einfaches Swing-Fenster");

fenster.setVisible(true);

}

}

Page 13: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

13

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 551 – 00 – TH – 03

------------------------------------------------------------------------------------

Die Klasse Color (Package java.awt)

Allgemeines

◇ Objekte der Klasse Color dienen zur Beschreibung von Farben.

Sie werden z.B. zum Setzen der Hintergrund- und Vordergrundfarbe von GUI-Komponenten benötigt

◇ Objekte dieser Klasse legen eine Farbe durch deren Rot- Grün- und Blau-Anteile (RGB-Werte) fest.

Jeder Anteil wird durch einen int-Wert im Bereich 0 ... 255 repräsentiert. Er lässt sich auch durch einen

float-Wert im Bereich 0.0 ... 1.0 angeben.

◇ Eine weitere Datenkomponente dient zur Beschreibung der Farb-Transparenz (Alpha-Wert).

Auch dieser Wert wird entweder als int-Wert (Bereich 0 ... 255) oder als float-Wert (Bereich 0.0 ...

1.0) angegeben.

Dabei bedeutet

- der Wert 0 bzw 0.0 vollkommen durchsichtig (nicht opak),

- der Wert 255 bzw 1.0 vollkommen undurchsichtig (opak)

◇ Objekte für 13 häufig verwendete Farben sind vordefiniert und stehen als Klassen-Konstante zur Verfügung :

Von Color.BLACK über Color.GREEN bis Color.YELLOW

Konstruktoren

◇ Beliebige Color-Objekte lassen sich unter Angabe der RGB-Werte und gegebenenfalls des Alpha-Werts mit Hilfe

der folgenden Konstruktoren erzeugen:

Memberfunktionen zur Ermittlung der Farb-Komponenten

◇ Neben zahlreichen anderen Memberfunktionen existieren die folgenden Methoden zum Ermitteln der einzelnen

Farbkomponenten eines Color-Objekts.

public Color(int r, int g, int b) Erzeugung eines Color-Objekts mit den angegebenen

RGB-Werten und einem Alpha-Wert von 255

(vollkommen undurchsichtig)

public Color(float r, float g, float b) Erzeugung eines Color-Objekts mit den angegebenen

RGB-Werten und einem Alpha-Wert von 1.0

(vollkommen undurchsichtig)

public Color(int r, int g, int b, Erzeugung eines Color-Objekts mit den angegebenen

int a) RGB-Werten und dem angegebenen Alpha-Wert (a)

public Color(float r, float g, float b, Erzeugung eines Color-Objekts mit den angegebenen

float a) RGB-Werten und dem angegebenen Alpha-Wert (a)

public int getRed() Ermittlung der Rot-Komponente im Bereich 0 ... 255

public int getGreen() Ermittlung der Grün-Komponente im Bereich 0 ... 255

public int getBlue() Ermittlung der Blau-Komponente im Bereich 0 ... 255

public int getAlpha() Ermittlung des Alpha-Werts im Bereich 0 ... 255

Page 14: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

14

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 552 – 00 – TH – 02

-----------------------------------------------------------------------------------

Die Klasse Font (Package java.awt)

Allgemeines

◇ Objekte der Klasse Font repräsentieren Schriftarten.

◇ Die Methode setFont() der Klasse Component dient zur Festlegung der in einer GUI-Komponente zu ver-

wendenden Schriftart. Ihr ist ein Font-Objekt als Parameter zu übergeben.

Wird für eine GUI-Komponente keine Schriftart explizit festgelegt (kein Aufruf der Methode setFont() oder

ein Aufruf mit null als aktuellem Parameter), so erbt diese Komponente die in ihrem Container eingesetzte Schriftart.

Defaultmässig wird ein systemabhängiger Standard-Font verwendet.

◇ Eine Schriftart wird durch drei Parameter festgelegt :

▻ Font-(Familien-)Name

▻ Schriftstil

▻ Schriftgröße

◇ Font-(Familien-)Name Als Font-(Familien-)Name wird i.a. ein Name für einen logischen Font angegeben, der von der Java-Laufzeitumgebung

auf einen im System real vorhandenen Font (physikalischen Font) abgebildet wird.

Von jedem Java-System werden die folgenden logischen Font-Familien-Namen unterstützt :

▻ "Serif" systemspezifische Proportionalzeichensatz-Familie TimesRoman

Umsetzung unter Windows : True-Type-Font Times New Roman

▻ "SansSerif" systemspezifische Proportionalzeichensatz-Familie Helvetica

Umsetzung unter Windows : True-Type-Font Arial

▻ "Monospaced" systemspezifische Nichtproportionalzeichensatz-Familie Courier

Umsetzung unter Windows : True-Type-Font Courier New

◇ Schriftstil

Spezifizierung durch einen int-Wert. Hierfür sind in der Klasse Font die folgenden Konstanten definiert :

▻ Font.PLAIN (0) normale Schrift

▻ Font.BOLD (1) fette Schrift

▻ Font.ITALIC (2) kursive Schrift Die Schriftstile Font.BOLD und Font.ITALIC können auch miteinander kombiniert werden (Addition oder

bitweis-Oder) fette und kursive Schrift.

◇ Schriftgröße

Angabe in Punkt (Pt) durch einen int-Wert. Übliche Punktgrößen für normale Textdarstellung : 10 oder 12 Pt.

Konstruktor

◇ Font-Objekte können mit Hilfe des folgenden Konstruktors erzeugt werden :

Memberfunktionen zur Ermittlung der Font-Komponenten

public Font(String name, int style, int size) Erzeugung eines neuen Font-Objekts mit dem

Namen name, Stil style und Größe size

public String getName() Ermittlung des logischen Font-Familien-Namens

public String getFamily() Ermittlung des physikalischen Font-Familien-Namens

public int getStyle() Ermittlung des Schriftstils

public int getSize() Ermittlung der Schriftgröße in Punkt

Page 15: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

15

FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 553 – 01 – TH – 04

-----------------------------------------------------------------------------------

Layout-Manager in Java (1)

Allgemeines

◇ Üblicherweise wird die Anordnung (Größe und Position) der in einem Container enthaltenen Komponenten durch

einen Layout-Manager vorgenommen.

Prinzipiell können die einzelnen Komponenten zwar "Hinweise" zu ihrer Größe, Position und Ausrichtung enthalten,

diese müssen aber nicht vom Layout-Manager berücksichtigt werden. Vielmehr hat dieser das "letzte Wort" bezüglich

der Anordnung.

◇ Es ist auch möglich, auf einen Layout-Manager zu verzichten und mit absoluter Positionierung zu arbeiten. Dies erfor-

dert dann eine genaue Festlegung der Größe und der Position jeder einzelnen Komponente und führt zu Anpassungs-

problemen, wenn die Größe des Top-Level-Containers bzw die Ausführungs-Plattform verändert wird

◇ Ein Layout-Manager ist ein Objekt einer Klasse, die das Interface LayoutManager (Package java.awt)

implementiert.

Dieses Interface definiert Methoden, die für die Anordnung von GUI-Komponenten innerhalb eines Containers benötigt

werden.

◇ Für erweiterte Layout-Fähigkeiten ist das von LayoutManager abgeleitete Interface LayoutManager2

definiert. Es enthält Methoden, die es einem Layout-Manager ermöglichen, durch contraints-Objekte festgelegte Anord-

nungs-Beschränkungen / -Vorgaben explizit zu berücksichtigen.

contraints-Objekte (häufig String-Objekte) spezifizieren wie und wo Komponenten in das Layout einzufügen sind.

◇ Die Java-Bibliothek stellt eine Reihe von Layout-Manager-Klassen zur Verfügung.

Die einzelnen Klassen unterscheiden sich insbesondere hinsichtlich der Unterteilung der Gesamtfläche eines Containers

in verschiedene Bereiche und die Zuordnung dieser Bereiche zu den im Container enthaltenen Komponenten. Einige

Layout-Manager passen dabei die Komponenten in ihrer Groesse an oder fügen Zwischenräume zwischen ihnen ein.

Einige von ihnen implementieren nur das Interface LayoutManager, andere das Interface LayoutManager2.

Layout-Manager-Klassen sind sowohl im Package java.awt als auch im Package javax.swing definiert Die am häufigsten verwendeten Layout-Manager-Klassen sind :

▻ BorderLayout (Package java.awt)

▻ FlowLayout (Package java.awt)

▻ GridLayout (Package java.awt)

▻ BoxLayout (Package javax.swing)

▻ GridBagLayout (Package java.awt)

◇ Defaultmässig ist in den meisten GUI-Container-Klassen das BorderLayout eingestellt.

Ausnahmen :

- Für die Klassen Panel und JPanel ist FlowLayout voreingestellt.

- Für die Klasse Box (Package javax.swing) ist BoxLayout voreingestellt Ein anderer Layout-Manager kann mit der in der Klasse Container definierten Methode void setLayout(LayoutManager mgr) für jedes Container-Objekt individuell festgelegt werden Dabei lassen sich die im Package javax.swing definierten Layout-Manager-Klassen nur für Swing-Komponenten

einsetzen, während die im Package java.awt enthaltenen Layout-Manager-Klassen sowohl für AWT- als auch

für Swing-Komponenten Anwendung finden.

Page 16: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

16

FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 553 – 02 – TH – 02

-----------------------------------------------------------------------------------

Layout-Manager in Java (2)

Die Klasse BorderLayout (Package java.awt)

◇ Dieser Layout-Manager teilt den Container in fünf Gebiete ein : "Norden", "Süden", "Westen", Osten" und "Zentrum".

In jedes dieser Gebiete kann er genau eine Komponente einfügen.

◇ Die einzelnen Komponenten werden in ihrer Größe so angepasst, dass sie insgesamt den gesamten Container ausfüllen.

Allerdings können sowohl horizontale als auch vertikale Abstände zwischen den Komponenten festgelegt werden. Die Komponenten im "Norden" und "Süden" bekommen ihre bevorzugte Höhe und werden in der Breite an die Con-

tainergröße angepasst

Die Komponenten im "Westen" und "Osten" bekommen dagegen ihre bevorzugte Breite und werden in der Höhe an den

Container angepasst.

Die Komponente im "Zentrum" wird sowohl in der Höhe als auch in der Breite an den verbleibenden Bereich angepasst.

◇ Konstruktoren :

◇ Beim Einfügen einer Komponente in einen Container (mittels add()) ist üblicherweise das Gebiet, in dem sie platziert

werden soll, anzugeben.

Für diese Angabe sind die folgenden in der Klasse BorderLayout definierten (String-)Konstanten zu verwenden :

- BorderLayout.NORTH

- BorderLayout.SOUTH

- BorderLayout.WEST

- BorderLayout.EAST

- BorderLayout.CENTER Beispiel : Panel p = new Panel(); p.setLayout(new BorderLayout());

p.add(new Button("Okay"), BorderLayout.SOUTH); Wird keine Gebietsangabe beim Einfügen angegeben, wird die Komponente im "Zentrum" platziert.

◇ Wird die Größe des Containers geändert (z.B. durch Ziehen mit der Maus), so bleibt die Höhe der Komponenten im

"Norden" und "Süden" sowie die Breite der Komponenten im "Westen und "Osten" unverändert, während die jeweils

andere Dimension dieser Komponenten sowie beide Dimensionen der Komponente im "Zentrum" an die Größe des

Containers angepasst werden.

◇ Beispiel : Border-Layout eines JFrame-Containers mit fünf JButton-Komponenten

public BorderLayout() Erzeugung eines BorderLayout-Objekts, das die Kom-

ponenten ohne Zwischenabstände anordnet

public BorderLayout(int hgap, int vgap) Erzeugung eines BorderLayout-Objekts, das die Kom-

ponenten mit dem horizontalen Abstand hgap und dem

vertikalen Abstand vgap anordnet (Abstaende in Pixel)

Page 17: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

17

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 553 – 03 – TH – 01

-----------------------------------------------------------------------------------

Layout-Manager in Java (3)

Demonstrationsbeispiel zu Layout-Manager (hier : BorderLayout)

// LayoutDemo.java

import java.awt.*;

import javax.swing.*;

public class LayoutDemo extends JFrame

{

Container c;

JButton[] ba;

String titel;

public LayoutDemo()

{

c=getContentPane();

titel = "LayoutDemo : ";

ba = new JButton[5];

for (int i=0; i<ba.length; i++)

{

ba[i] = new JButton("Button "+(i+1));

ba[i].setAlignmentX(Component.CENTER_ALIGNMENT);

}

ba[2].setText(ba[2].getText()+" with long title");

ba[2].setFont(new Font("Serif", Font.ITALIC|Font.BOLD, 12));

ba[2].setBackground(Color.ORANGE);

useBorderLayout();

//useFlowLayout();

//useGridLayout();

//useBoxLayout();

setTitle(titel);

setSize(300, 170);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

private void useBorderLayout() // BorderLayout ist Default bei JFrame

{ c.add(ba[0], BorderLayout.NORTH);

c.add(ba[1], BorderLayout.SOUTH);

c.add(ba[2], BorderLayout.CENTER);

c.add(ba[3], BorderLayout.WEST);

c.add(ba[4], BorderLayout.EAST);

titel+="BorderLayout";

}

private void useFlowLayout()

{ //

}

private void useGridLayout()

{ //

}

private void useBoxLayout()

{ //

}

public static void main(String[] args)

{

new LayoutDemo().setVisisble(true);

}

}

Page 18: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

18

FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 553 – 04 – TH – 02

-----------------------------------------------------------------------------------

Layout-Manager in Java (4)

Die Klasse FlowLayout (Package java.awt)

◇ Dieser Layout-Manager fügt die Komponenten "fliessend" zeilenweise von links nach rechts in den Container ein.

Dabei bedeutet "fliessend", dass die Komponenten solange in der Reihenfolge ihres Einfügens nebeneinander platziert

werden, bis kein Platz mehr für die nächste Komponente vorhanden ist. Dann wird das Einfügen analog in der nächsten

Reihe fortgesetzt.

◇ Die Komponenten werden in ihrer bevorzugten Größe (Breite und Höhe) dargestellt. Defaultmässig werden die in einer Reihe befindlichen Komponenten zentriert ausgerichtet.

Zwischen den Komponenten wird sowohl horizontal als auch vertikal ein Abstand von 5 Pixel gesetzt.

Der vertikale Abstand bezieht sich dabei auf die Komponenten mit der jeweils größten Höhe. Sowohl die Ausrichtung als auch der Abstand in beiden Richtungen können geändert werden.

◇ Konstruktoren :

◇ Zur Angabe der Komponenten-Ausrichtung in den einzelnen Zeilen (Konstruktor-Parameter align) stehen in der

Klasse FlowLayout die folgenden Konstanten zur Verfügung :

- FlowLayout.LEFT (Ausrichtung linksbündig)

- FlowLayout.RIGHT (Ausrichtung rechtsbündig)

- FlowLayout.CENTER (Ausrichtung zentriert, default)

◇ Wird die Größe des Containers geändert (z.B. durch Ziehen mit der Maus), so wird die Zuordnung der Komponen-

ten zu den einzelnen Zeilen entsprechend angepasst.

◇ Beispiel : Flow-Layout eines JFrame-Containers mit fünf JButton-Komponenten

(Ergänzung / Modifikation des obigen Demonstrationsprogramms)

public FlowLayout() Erzeugung eines FlowLayout-Objekts, mit den Default-

einstellungen (zentrierte Ausrichtung und vertikaler und

horizontaler Abstand von 5 Pixel)

public FlowLayout(int align) Erzeugung eines FlowLayout-Objekts, mit einer durch

align festgelegten Ausrichtung und einem vertikalen und

horizontalen Abstand von 5 Pixel

public FlowLayout(int align, int hgap, Erzeugung eines FlowLayout-Objekts, mit einer durch

int vgap) align festgelegten Ausrichtung und einem durch hgap

(horizontal) und vgap (vertikal) gegebenen Abstand

private void useFlowLayout()

{ c.setLayout(new FlowLayout());

for (int i=0; i<ba.length; i++)

c.add(ba[i]);

titel+="FlowLayout";

}

Page 19: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

19

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 553 – 05 – TH – 02

-----------------------------------------------------------------------------------

Layout-Manager in Java (5)

Die Klasse GridLayout (Package java.awt)

◇ Dieser Layout-Manager teilt die Containerfläche in gitter- bzw tabellenartig angeordnete Zellen auf.

Die Zellen sind Rechtecke gleicher Größe. Diese Größe ergibt sich aus der Containergröße und der Anzahl von Zeilen

und Spalten. In jedem dieser Rechtecke wird genau eine Komponente platziert.

Standardmässig (horizontale Ausrichtung,von links nach rechts) werden die Komponenten in der Reihenfolge ihres

Einfügens zeilenweise von links nach rechts angeordnet.

◇ Die Größe der Komponenten wird an die Zellen-Größe angepasst, so dass der in der Zelle verfügbare Platz voll ausge-

nutzt wird. Alle Komponenten haben somit die gleiche Größe.

Defaultmässig besteht zwischen den Zellen kein Abstand. Es kann aber sowohl ein vertikaler als auch ein horizontaler

Abstand festgelegt werden.

◇ Die Anzahl der Zeilen und Spalten können angegeben werden (im Konstruktor oder mittels Memberfunktionen).

Wenigstens einer der beiden Werte muss von 0 verschieden sein. Der Wert 0 bedeutet "beliebig viele".

Wenn beide Werte von 0 verschieden sind, wird der Wert für die Anzahl der Spalten ignoriert. In diesem Fall wird

die tatsächliche Anzahl der Spalten aus der festgelegten Anzahl der Zeilen und der Komponenten-Anzahl ermittelt.

Die explizite Angabe einer Spalten-Anzahl beeinflusst das Layout nur dann, wenn für die Anzahl der Zeilen 0 angege-

ben wird. Wird weder die Anzahl der Zeilen noch die Anzahl der Spalten explizit festgelegt, wird die Zeilenzahl

defaultmässig auf 1 gesetzt. Die Anzahl der Spalten ergibt sich dann aus der Anzahl der Komponenten.

◇ Konstruktoren :

◇ Wird die Größe des Containers geändert (z.B. durch Ziehen mit der Maus), so wird – bei gleichbleibender Zeilen-

und Spaltenzahl – die Größe der Zellen und damit die Größe der Komponenten an die jeweilige Gesamtgröße des

Containers angepasst.

◇ Beispiel : Grid-Layout eines JFrame-Containers mit fünf JButton-Komponenten (3 Zeilen, 2 Spalten)

(Ergänzung / Modifikation des obigen Demonstrationsprogramms)

public GridLayout() Erzeugung eines GridLayout-Objekts, mit einer Zeile,

beliebig vielen Spalten, kein Abstand zwischen den Zellen

public GridLayout(int rows, int cols) Erzeugung eines GridLayout-Objekts, mit rows Zeilen

und cols Spalten (tatsächliche Auswirkung siehe oben),

kein Abstand zwischen den Zellen

public GridLayout(int rows, int cols, Erzeugung eines GridLayout-Objekts, mit rows Zeilen

int hgap, int vgap) und cols Spalten (siehe oben), sowie einem durch hgap

(horizontal) und vgap (vertikal) gegebenen Zellen-Abstand

private void useGridLayout()

{ c.setLayout(new GridLayout(3,2));

for (int i=0; i<ba.length; i++)

c.add(ba[i]);

titel+="GridLayout(3,2)";

}

Page 20: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

20

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 553 – 06 – TH – 02

------------------------------------------------------------------------------------

Layout-Manager in Java (6)

Die Klasse BoxLayout (Package javax.swing)

◇ Dieser Layout-Manager ordnet die Komponenten – gemäß ihrer Einfüge-Reihenfolge - entweder horizontal in einer

Zeile oder vertikal in einer Spalte an. Die Anordnungs-Achse ist jeweils festzulegen (kein Default).

◇ Er berücksichtigt hierbei sowohl die für die einzelnen Komponenten eingestellten Größen-Parameter (minimale, maxi-

male und bevorzugte Größe) als auch deren festgelegte vertikale und horizontale Ausrichtung. Grundsätzlich versucht er die Komponenten in ihrer bevorzugten Größe darzustellen.

Sind bei vertikaler Anordnung die bevorzugten Breiten der Komponenten unterschiedlich, wird versucht, unter Be-

rücksichtigung der jeweiligen maximalen Breiten, die Breite aller Komponenten an die größte bevorzugte Breite anzu-

passen.

Ist das nicht möglich, z.B. weil die maximalen Größen es nicht zulassen, werden die Komponenten in ihrer bevorzugten

Breite dargestellt. Die horizontale Ausrichtung der Komponenten (sowohl untereinander als auch innerhalb des Contai-

ners) richtet sich nach deren – defaultmässig vorgegebener bzw explizit gesetzter – horizontaler (X-) Ausrichtung. Analoges gilt für die horizontale Anordung.

Werden die Komponenten mit unterschiedlicher Höhe dargestellt, richtet sich ihre vertikale Ausrichtung nach der

für die einzelnen Komponenten eingestellten vertikalen (Y-) Ausrichtung (Default ist.i.a. zentriert)

◇ Zwischen den Komponenten wird kein Abstand eingefügt.

Zum Erzeugen von Abständen können spezielle unsichtbare Füll-Komponenten eingesetzt werden.

◇ Konstruktor :

◇ Zur Festlegung der Anordnungs-Achse (Konstruktor-Parameter axis) stehen in der Klasse BoxLayout die folgen-

den Konstanten zur Verfügung :

- BoxLayout.X_AXIS (horizontale Anordnung, in einer Zeile)

- BoxLayout.Y_AXIS (vertikale Anordnung, in einer Spalte)

- BoxLayout.LINE_AXIS (Bedeutung sprachabhängig, bei europäischen Sprachen : horizontale Anordnung)

- BoxLayout.PAGE_AXIS (Bedeutung sprachabhängig, bei europäischen Sprachen : vertikale Anordnung)

◇ Bei einer Größenänderung des Containers (z.B. durch Ziehen mit der Maus), behalten die Komponenten ihre ur-

sprüngliche Größe, Anordnung und Ausrichtung (zueinander und im Container).

◇ Beispiel : Box-Layout eines JFrame-Containers mit fünf JButton-Komponenten (vertikale Anordnung)

(Ergänzung / Modifikation des obigen Demonstrationsprogramms)

public BoxLayout(Container con, int axis) Erzeugung eines BoxLayout-Objekts für das

Container-Objekt con mit der durch axis

festgelegten Anordnungs-Achse

private void useBoxLayout()

{ c.setLayout(new BoxLayout(c, BoxLayout.Y_AXIS));

for (int i=0; i<ba.length; i++)

c.add(ba[i]);

titel+="BoxLayout";

}

Page 21: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

21

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 554 – 01 – TH – 04

-----------------------------------------------------------------------------------

Umrandungen für Swing-Komponenten in Java (1)

Umrandungen und das Interface Border (Package javax.swing.border)

◇ Swing-GUI-Komponenten (genauer : Objekte aller von JComponent abgeleiteten Klassen) können mit einer

Umrandung versehen werden.

Derartige Umrandungen können u.a. dazu dienen :

- GUI-Komponenten mit einer Dekoration zu versehen

- um rahmenlose GUI-Komponenten einen Rahmen zu zeichnen

- für GUI-Komponenten einen Namen anzugeben

- GUI-Komponenten mit Abstandsflächen zu versehen.

◇ Umrandungen werden durch Border-Objekte beschrieben.

Zum Setzen einer Umrandung muß die in JComponent definierte Memberfunktion setBorder() mit einem

Border-Objekt als Parameter für das entsprechende GUI-Komponenten-Objekt aufgerufen werden.

◇ Border-Objekte sind Objekte von Klassen, die das Interface Border implementieren.

Klassen für Border-Objekte

◇ In der Java-Standard-Bibliothek – u.a. im Package javax.swing.border – sind zahlreiche Klassen, die das

Interface Border implementieren, definiert.

Einige der im Package javax.swing.border enthaltenen Klassen sind :

▻ AbstractBorder abstrakte Basisklasse für konkrete Border-Klassen

▻ EmptyBorder Klasse für "leere" Umrandungen Abstandsflächen

▻ LineBorder Klasse für Umrahmungen mit "normalen" Linien

▻ EtchedBorder Klasse für Umrahmungen mit eingeprägten bzw herausgearbeiteten Linien

▻ TitledBorder Klasse für mit einem Titel versehene Umrandungen

▻ CompoundBorder Klasse zur Zusammenfassung von zwei Umrandungen zu einer einzigen

◇ Es ist auch möglich eigene Border-Klassen zu definieren.

Diese sind zweckmässigerweise von der Klasse AbstractBorder abzuleiten.

Anwendungung von Umrandungen

◇ Prinzipiell können Umrandungen um jedes Objekt einer von JComponent abgeleiteten Klasse gesetzt werden.

◇ Jedoch arbeitet die LaF-Implementierung vieler Standard-Swing-Komponenten nicht sehr gut mit explizit gesetzten

Umrandungen.

Es wird daher empfohlen, Umrandungen grundsätzlich nur für JPanel- und JLabel-Komponenten zu verwenden.

Bei Komponenten dieser Klassen treten keine Probleme auf.

◇ Sollen andere Swing-Komponenten mit einer Umrandung versehen werden, so sollten diese zweckmässigerweise in

jeweils eine JPanel-Komponente eingebettet werden und um diese dann die Umrandung gesetzt werden.

Erzeugung von Border-Objekten

◇ Ein Border-Objekt kann von mehreren GUI-Komponenten-Objekten gemeinsam genutzt werden.

Daher ist es üblich und zweckmässig , Border-Objekte nicht mittels eines new-Ausdrucks zu erzeugen, sondern

hierfür statische Erzeugungs-Methoden der Klasse BorderFactory (Package javax.swing) einzusetzen

(Verwendung von Border-Objekten als Singletons).

Page 22: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

22

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 554 – 02 – TH – 05

------------------------------------------------------------------------------------

Umrandungen für Swing-Komponenten in Java (2)

Die Klasse BorderFactory (Package javax.swing)

◇ Die Klasse BorderFactory stellt u.a. die folgenden statischen Erzeugungs-Methoden für Border-Objekte

bereit (Auswahl) :

public static Border createEmptyBorder(int top, int left, int bottom, int right)

Erzeugung eines EmptyBorder-Objekts mit den durch die Parameter festgelegten Größen (in Pixel)

public static Border createLineBorder(Color col, int thick)

Erzeugung eines LineBorder-Objekts, das die Farbe col und die Linien-Stärke thick (in Pixel) verwendet

public static Border createLineBorder(Color col)

Erzeugung eines LineBorder-Objekts, das die Farbe col und einen Defaultwert für die Linien-Stärke verwendet

public static Border createEtchedBorder()

Erzeugung eines EtchedBorder-Objekts für eingeprägte (etched-in) Umrandungen, das die aktuelle Hintergrundfarbe

des zu umrandenden Objekts für Hervorhebungen und Abschattungen verwendet

public static Border createEtchedBorder(int type)

Erzeugung eines EtchedBorder-Objekts für den durch type festgelegten Umrandungstyp, das die aktuelle Hinter-

grundfarbe des zu umrandenden Objekts für Hervorhebungen und Abschattungen verwendet

Zulässige Werte für type : EtchedBorder.RAISED herausgearbeitete Umrandung (etched-out)

EtchedBorder.LOWERED eingeprägte Umrandung (etched-in)

public static Border createEtchedBorder(int type, Color highlight, Color shadow)

Erzeugung eines EtchedBorder-Objekts für den durch type festgelegten Umrandungstyp, das die Farbe

highlight für Hervorhebungen und die Farbe shadow für Abschattungen verwendet

public static TitledBorder createTitledBorder(String str)

Erzeugung eines TitledBorder-Objekts, das die Beschriftung str und Defaultwerte für die übrigen Kenngrößen

verwendet.

Diese Defaultwerte sind : eingeprägte (?) Umrandung, Text auf oberem Rand, linksbündig, Font und Textfarbe durch die

Defaultwerte des aktuellen LaF bestimmt

public static TitledBorder createTitledBorder(Border bord, String str)

Erzeugung eines TitledBorder-Objekts aus dem existierenden Border-Objekt bord, das die Beschriftung

str sowie Defaultwerte für die Textposition (oberer Rand), die Textausrichtung (linksbündig) und Font und Textfarbe

(Defaultwerte des aktuellen LaF) verwendet.

public static TitledBorder createTitledBorder(Border bord, String str, int just,

int pos)

Erzeugung eines TitledBorder-Objekts aus dem existierenden Border-Objekt bord, das die Beschriftung

str sowie die Textposition pos, die Textausrichtung just und Defaultwerte für Font und Textfarbe (Defaultwerte

des aktuellen LaF) verwendet. Zulässige Werte für just und pos siehe Java-API-Doc

public static TitledBorder createTitledBorder(Border bord, String str, int just,

int pos, Font fnt, Color col)

Erzeugung eines TitledBorder-Objekts aus dem existierenden Border-Objekt bord, das die Beschriftung

str sowie die Textposition pos, die Textausrichtung just, den Font fnt und die Farbe col verwendet.

Zulässige Werte für just und pos siehe Java-API-Doc

public static CompoundBorder createCompoundBorder(Border out, Border in)

Erzeugung eines CompoundBorder-Objekts aus den existierenden Border-Objekten out (äussere Umrandung)

und in (innere Umrandung)

Page 23: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

23

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 554 – 03 – TH – 02

------------------------------------------------------------------------------------

Umrandungen für Swing-Komponenten in Java (3)

Demonstrationsprogramm zu Umrandungen

// MultiBorderDemo.java

import java.awt.*;

import javax.swing.*;

import javax.swing.border.*;

public class MultiBorderDemo extends JFrame

{ Container c;

JButton[] ba;

String titel;

public MultiBorderDemo(int sel)

{ c=getContentPane();

c.setLayout(new FlowLayout());

titel = "MultiBorderDemo";

JPanel[] pa = new JPanel[5];

for (int i=0; i<pa.length; i++)

{ pa[i] = new JPanel();

JButton but = new JButton("Button "+(i+1));

if(i==2)

{ but.setText(but.getText()+" with long title");

but.setFont(new Font("Serif", Font.ITALIC|Font.BOLD, 12));

but.setBackground(Color.ORANGE);

}

pa[i].add(but);

switch (sel)

{ case 1 :

pa[i].setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

break;

case 2 :

pa[i].setBorder(BorderFactory.createEtchedBorder());

break;

case 3 :

pa[i].setBorder(BorderFactory.createTitledBorder("button"));

break;

case 4 :

Border inbord = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);

Border outbord = BorderFactory.createLineBorder(Color.GREEN, 5);

pa[i].setBorder(BorderFactory.createCompoundBorder(outbord, inbord));

break;

default :

break;

}

c.add(pa[i]);

}

setTitle(titel);

setSize(300, 240);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

public static void main(String[] args)

{

if (args.length==1)

new MultiBorderDemo(Integer.parseInt(args[0])).setVisible(true);

else

new MultiBorderDemo(0).setVisible(true);

}

}

Page 24: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

24

FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 554 – 04 – TH – 01

-----------------------------------------------------------------------------------

Umrandungen für Swing-Komponenten in Java (4)

Beispiele für Umrandungen (vom Demonstrationsprogramm MultiBorderDemo erzeugte Fenster) keine Umrandung Umrandung mit EmptyBorder

Umrandung mit EtchedBorder Umrandung mit TitledBorder

Umrandung mit CompoundBorder aus Etchedborder und LineBorder

Page 25: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

25

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 561 – 00 – TH – 06

------------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (1)

Die Klasse JFrame (Package javax.swing)

◇ Wichtigste Swing-Top-Level-Container-Klasse

◇ Im Unterschied zur AWT-Top-Level-Container-Klasse Frame, von der JFrame abgeleitet ist, werden in einen

JFrame-Container die Komponenten nicht direkt eingefügt. Vielmehr besitzt jeder JFrame-Container, wie jeder

andere Swing-Top-Level-Container, einen speziellen Einfüge-Container, die sogenannte content pane.

Die content pane umfasst den gesamten "normalen" Einfüge-Bereich des Top-Level-Containers. In den Top-Level-

Container aufzunehmende Komponenten werden in seine content pane eingefügt.

Auch das Setzen eines Layout-Managers erfolgt in der content pane und nicht direkt im JFrame-Container. Anmerkung : Ab dem JDK 5.0 sind die Methoden add(), remove() und setLayoutManager() für die

Klasse JFrame so überschrieben, dass sie implizit die content pane verwenden. Sie können damit direkt für

JFrame-Container aufgerufen werden.

◇ Zusätzlich kann ein JFrame-Container über eine Menü-Leiste verfügen. Falls vorhanden, befindet sich diese ausser-

halb der content pane. Sie wird direkt in den Top-Level-Container eingefügt.

Weiterhin kann ein JFrame-Container eine Werkzeugleiste besitzen.

Diese wird analog zu anderen Komponenten in die content pane eingefügt.

◇ Als weiterer Unterschied zur AWT-Klasse Frame ist in der Klasse JFrame bereits – ohne explizite Registrierung

eines Window-Listeners – eine Reaktions-Funktionalität auf das Schliessen des Fensters implementiert.

Die genaue Reaktion kann mittels der Memberfunktion public void setDefaultCloseOperation(int op)

festgelegt werden.

Als gültige Werte für den Parameter op können die folgenden Konstanten verwendet werden :

- WindowConstants.DO_NOTHING_ON_CLOSE keine Reaktion

- WindowConstants.HIDE_ON_CLOSE das Fenster verstecken (unsichtbar machen), Default

- WindowConstants.DISPOSE_ON_CLOSE das Fenster verstecken und zerstören

- JFrame.EXIT_ON_CLOSE das Programm beenden (mittels System.exit(0))

◇ Konstruktoren (Auswahl)

◇ Memberfunktionen (Auswahl) *) geerbt von Frame **) geerbt von Window

◇ Beispiel zum Einfügen von Komponenten JFrame frame = new JFrame();

Container c = frame.getContentPane();

c.setLayout(new FlowLayout()); // ab JDK 5.0 auch : frame.setLayout(...)

c.add(new JLabel("Hallo")); // ab JDK 5.0 auch : frame.add(...)

public JFrame() Erzeugung eines JFrame-Objekts ohne Titel, das durch das Objekt repräsen-

tierte Fenster ist unsichtbar

public JFrame(String title) Erzeugung eines JFrame-Objekts mit dem Titel title, das durch das

Objekt repräsentierte Fenster ist unsichtbar

public Container getContentPane() Ermitteln der content pane

public void setDefaultCloseOperation(int op) Setzen der Reaktion auf das Schliessen des Fensters

public void setJMenuBar(JMenuBar menu) Einfügen der Menuleiste menu

public void setTitle(String title) *) Setzen des Titels auf title

public void dispose() **) Zerstören des Fensters

public void pack() Anpassen der Fenstergröße so, dass alle darin enthaltenen Komponenten gerade Platz haben

**) (Berechnung des Platzbedarfs an Hand der bevorzugten Größe der Komponenten)

Page 26: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

26

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 562 – 00 – TH – 07

------------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (2)

Die Klasse JDialog (Package javax.swing)

◇ Diese Top-Level-Container-Klasse wird typischerweise dazu benutzt, temporär auf dem Bildschirm erscheinende

Fenster zu erzeugen, die für einen kurzen Dialog mit dem Benutzer vorgesehen sind ( Dialog-Fenster, Dialog-Box)

◇ Ein Dialog-Fenster ist üblicherweise an einen JFrame-Container oder ein anderes Dialog-Fenster gebunden

("Besitzer" des Dialog-Fensters). Es wird zusammen mit seinem "Besitzer" ikonifiziert/de-ikonifiziert oder geschlossen.

◇ Dialog-Fenster können modal gestaltet werden.

Das bedeutet, dass während der Sichtbarkeit eines Dialog-Fensters alle anderen Fenster des Programms (also auch

sein "besitzendes" Fenster) für Benutzereingaben gesperrt ist.

Die anderen Fenster können erst wieder verwendet werden, wenn der Dialog abgewickelt, d.h. das Dialog-Fenster wieder

geschlossen ist.

◇ Wie ein JFrame-Objekt besitzt auch ein JDialog-Objekt eine content pane.

In diese – und nicht direkt in das JDialog-Objekt – müssen aufzunehmende Komponenten eingefügt werden.

Auch ein eventueller Layout-Manager ist ebenfalls in der content pane zu setzen. Anmerkung : ab dem JDK 5.0 erfolgt dies implizit durch die für JDialog entsprechend überladenen Methoden

add() und setLayoutManager() (sowie das Entfernen durch remove())

◇ Ein JDialog-Objekt kann auch eine Menue-Leiste besitzen. Diese wird – wie bei JFrame-Objekten – direkt in

den Top-Level-Container und nicht in die content pane eingefügt.

◇ Konstruktoren (Auswahl)

Es existieren weitere Konstruktoren, mit denen statt eines Frame-(JFrame)-Objekts ein Dialog-(JDialog-)

Objekt als "Besitzer" festgelegt wird.

◇ Memberfunktionen (Auswahl) Die als Auswahl bei der Klasse JFrame angegebenen Memberfunktionen existieren auch für die Klasse JDialog : public Container getContentPane() public void setDefaultCloseOperation(int op) Der Wert EXIT_ON_CLOSE für op ist nicht zulässig public void setJMenuBar(JMenuBar menu) public setTitle(String title) *) geerbt von Dialog

public void dispose() **) geerbt von Window

public void pack() **) geerbt von Window Einige weitere Memberfunktionen (geerbt von Dialog) :

public JDialog() Erzeugung eines nicht-modalen JDialog-Objekts ohne Titel und ohne

explizit spezifizierten "Besitzer".

Ein verborgenes Frame-Objekt wird implizit als "Besitzer" gesetzt

public JDialog(Frame owner) Erzeugung eines nicht-modalen JDialog-Objekts ohne Titel und dem

Frame-(JFrame-)Objekt owner als "Besitzer"

public JDialog(Frame owner, Erzeugung eines nicht-modalen JDialog-Objekts mit dem Titel tit und

String tit) dem Frame-(JFrame-)Objekt owner als "Besitzer"

public JDialog(Frame owner, Erzeugung eines JDialog-Objekts ohne Titel und dem Frame-(JFrame-)

boolean mod) Objekt owner als "Besitzer". Der Parameter mod bestimmt die Modalität :

modal, wenn true, nicht-modal, wenn false

public JDialog(Frame owner, Erzeugung JDialog-Objekts mit dem Titel tit und dem Frame-

String tit, (JFrame-) Objekt owner als "Besitzer". Der Parameter mod bestimmt die

boolean mod) Modalität : modal, wenn true, nicht-modal, wenn false

public void setModal(boolean mod) Setzen der Modalität auf modal, wenn mod == true

public boolean isModal() Ermittlung der Modalität,

Rückgabewert : true, wenn modal, false andernfalls

Page 27: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

27

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 563 – 01 – TH – 03

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (3-1)

Die Klasse JOptionPane (Package javax.swing)

◇ Diese Klasse ermöglicht auf relativ einfache Art und Weise die Erzeugung einfacher Standard-Dialog-Fenster.

◇ Die erzeugbaren Standard-Dialog-Fenster informieren den Programmbenutzer über irgendetwas und/oder fordern ihn zu

einer Eingabe auf.

◇ Die erzeugbaren Standard-Dialog-Fenster sind modal und können in der Größe nicht verändert werden.

◇ Als einfachste Möglichkeit zur Dialog-Fenster-Erzeugung stehen eine Reihe statischer Methoden zur Verfügung. Diese Methoden

▻ erzeugen ein weitgehend vorkonfiguriertes Dialog-Fenster, stellen es dar,

▻ warten auf eine zum Schliessen des Fensters führende Benutzeraktion (Schaltknopf-Betätigung, String-Eingabe)

▻ und liefern gegebenenfalls das Ergebnis der Benutzeraktion als Funktionswert zurück.

◇ Einige statische Klassen-Methoden als Beispiele :

Der bei allen Methoden vorhandene Parameter parent legt die Komponente fest, für die der Dialog jeweils aus-

geführt wird (null ist zulässig)

public static void showMessageDialog(Component parent, Object msg,

String title, int typeMsg)

Erzeugen eines Meldungs-Dialog-Fensters mit dem Titel title, das die Meldung msg (meist ein String) ausgibt und

ein durch den Meldungs-Typ typeMsg festgelegtes Default-Icon darstellt.

Zulässige Werte für den Meldungs-Typ typeMsg : JOptionPane.ERROR_MESSAGE

JOptionPane.INFORMATION_MESSAGE

JOptionPane.WARNING_MESSAGE

JOptionPane.QUESTION_MESSAGE

JOptionPane.PLAIN_MESSAGE (kein Icon)

public static void showMessageDialog(Component parent, Object msg)

Erzeugen eines Meldungs-Dialog-Fensters mit dem Titel "Message", das die Meldung msg (meist ein String) aus-

gibt und das Default-Icon für den Typ INFORMATION_MESSAGE darstellt

public static int showConfirmDialog(Component parent, Object msg,

String title, int typeOpt)

Erzeugen eines Bestätigungs-Dialog-Fensters mit dem Titel title, das die Meldung msg (meist ein String) ausgibt

und das Icon für QUESTION_MESSAGE sowie die durch den Options-Typ typeOpt festgelegten Options-Schalt-

knöpfe darstellt und auf die Auswahl eines Schaltknopfes wartet.

Zulässige Werte für den Options-Typ typeOpt : JOptionsPane.YES_NO_CANCEL_OPTION

JOptionsPane.YES_NO_OPTION

JOptionsPane.OK_CANCEL_OPTION

JOptionsPane.DEFAULT_OPTION (nur OK)

Der vom Benutzer ausgewählte Options-Schaltknopf bestimmt den zurückgegebenen Funktioswert (z.B. YES_OPTION)

public static int showConfirmDialog(Component parent, Object msg)

Erzeugen eines Bestätigungs-Dialog-Fensters mit einem Default-Titel, das die Meldung msg (meist ein String) ausgibt

und das Icon für QUESTION_MESSAGE sowie die Schaltknöpfe für den Options-Typ YES_NO_CANCEL_OPTION

darstellt und auf die Auswahl eines Schaltknopfes wartet.

Der vom Benutzer ausgewählte Options-Schaltknopf bestimmt den zurückgegebenen Funktioswert (z.B. YES_OPTION)

public static String showInputDialog(Component parent, Object msg)

Erzeugen eines Frage-Dialog-Fensters mit dem Titel "Input" (bzw "Eingabe"), das die Meldung msg (meist

ein String) ausgibt, das Icon für QUESTION_MESSAGE darstellt und auf die Eingabe eines Strings wartet.

Der vom Benutzer eingegebene String wird als Funktionswert zurückgegeben.

Page 28: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

28

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 563 – 02 – TH – 01

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (3-2)

Beispiele für von JOptionPane erzeugte Standard-Dialog-Fenster

// Meldungs-Dialog : Fehler-Meldung

JOptionPane.showMessageDialog(this,

"Lesefehler !",

"Eine Fehler-Meldung",

JOptionPane.ERROR_MESSAGE);

// Meldungs-Dialog : Information

JOptionPane.showMessageDialog(this,

"Die Festplatte ist zerstoert!",

"Eine Information",

JOptionPane.INFORMATION_MESSAGE);

// Meldungs-Dialog : Warnung

JOptionPane.showMessageDialog(this,

"Hoeren Sie auf !",

"Eine Warnung",

JOptionPane.WARNING_MESSAGE);

// Meldungs-Dialog : Frage

JOptionPane.showMessageDialog(this,

"Wollen Sie das wirklich ?",

"Eine Frage",

JOptionPane.QUESTION_MESSAGE);

// Bestätigungs-Dialog

// Default-Titel und

// Default-Options-Typ

int opt;

opt = JOptionPane.showConfirmDialog(this,

"Was wollen Sie ?");

// Frage-Dialog

// Default-Titel

String name;

name = JOptionPane.showInputDialog(this,

"Ihr Name ? ");

Page 29: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

29

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 564 – 00 – TH – 02

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (4)

Die Klasse JLabel (Package javax.swing)

◇ Diese Klasse dient zur Erzeugung von Beschriftungs-Objekten.

◇ Im Unterschied zu den AWT-Label-Objekten können JLabel-Objekte nicht nur Text, sondern auch Bilder dar-

stellen (auch beides kombiniert)

◇ Die Ausrichtung sowohl des Textes als auch des Bildes innerhalb des Darstellungsbereichs eines JLabel-Objekts

kann festgelegt werden.

Default-Ausrichtung für Text : horizontal linksbündig, vertikal zentriert

Default-Ausrichtung für Bilder : horizontal und vertikal zentriert Explizite Festlegung der Ausrichtung : SwingConstants.CENTER (zentriert)

SwingConstants.RIGHT (rechtsbündig)

SwingConstants.LEFT (linksbündig)

SwingConstants.TOP (obenbündig)

SwingConstants.BOTTOM (untenbündig)

◇ JLabel-Objekte können nicht auf vom Benutzer ausgelöste Ereignisse (Eingaben) reagieren.

◇ Konstruktoren (Auswahl)

◇ Memberfunktionen (Auswahl)

◇ Anmerkungen zu darzustellenden Bildern

▻ Bilder werden als Instanzen des Interfaces Icon (Package javax.swing) referiert.

Im Regelfall handelt es sich bei Ihnen um Objekte der dieses Interface implementierenden Klasse ImageIcon

▻ Objekte der Klasse ImageIcon (Package javax.swing) können aus einer Bild-Datei erzeugt werden mit dem

Konstruktor : public ImageIcon(String dateipfad) Der Parameter dateipfad spezifiziert die Bild-Datei.

public JLabel(String text) Erzeugung eines JLabel-Objekts mit dem Text text,

der Text ist horizontal linksbündig ausgerichtet

public JLabel(String text, int halign) Erzeugung eines JLabel-Objekts mit dem Text text,

der Text ist horizontal gemäß halign ausgerichtet

public JLabel(Icon image) Erzeugung eines JLabel-Objekts mit dem Bild image,

das Bild ist horizontal zentriert ausgerichtet

public JLabel(Icon image, int halign) Erzeugung eines JLabel-Objekts mit dem Bild image,

das Bild ist horizontal gemäß halign ausgerichtet

public String getText() Rückgabe des dargestellten Textes

public Icon getIcon() Rückgabe des dargestellten Bildes

public void setText(String text) Setzen des darzustellenden Textes auf text

public void setIcon(Icon image) Setzen des darzustellenden Bildes auf image

public void setHorizontalAlignment(int halign) Setzen der horizontalen Ausrichtung

gemäß halign (für Text und Bild)

public void setVerticalAlignment(int valign) Setzen der vertikalen Ausrichtung

gemäß valign (für Text und Bild)

Page 30: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

30

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 565 – 00 – TH – 03

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (5)

Die Klasse JButton (Package javax.swing)

◇ Diese Klasse dient zur Erzeugung von einfachen Schaltknöpfen (Schaltflächen).

◇ Auch JButton-Objekte können – im Unterschied zu den AWT-Button-Objekten – sowohl Text als auch ein Bild

(auch beides kombiniert) darstellen.

◇ Auch bei JButton-Objekten kann die Ausrichtung sowohl des Textes als auch des Bildes innerhalb ihres Darstel-

lungsbereichs festgelegt werden.

Default-Ausrichtung für Text und Bilder : horizontal rechtsbündig, vertikal zentriert Explizite Festlegung der Ausrichtung : SwingConstants.CENTER (zentriert)

SwingConstants.RIGHT (rechtsbündig)

SwingConstants.LEFT (linksbündig)

SwingConstants.TOP (obenbündig)

SwingConstants.BOTTOM (untenbündig)

◇ Im Unterschied zu JLabel-Objekten können JButton-Objekte (Schaltknöpfe !) vom Benutzer veranlasste Ereig-

nisse auslösen. Ein Schaltknopf kann auch den Focus besitzen und dann auch Tastatur-Eingaben empfangen.

Ein Schaltknopf kann vom Benutzer – z.B. durch einen Mausklick oder bei vorhandenen Focus durch die Leertaste –

betätigt ("gedrückt") werden. Ein "gedrückter" Schaltknopf ändert seine Hintergrundfarbe.

◇ Konstruktoren (Auswahl)

◇ Der überwiegende Teil der von der Klasse JButton angebotenen Schnittstelle ist geerbt von der Klasse AbstractButton.

Teilweise werden die gleichen Memberfunktionen – mit gleicher Funktionalität – wie bei der Klasse JLabel

zur Verfügung gestellt

Memberfunktionen (von AbstractButton geerbt, Auswahl)

public JButton() Erzeugung eines JButton-Objekts ohne "Inhalt"

public JButton(String text) Erzeugung eines JButton-Objekts das mit dem Text

text beschriftet ist (horizontal rechtsbündig ausgerichtet)

public JButton(Icon image) Erzeugung eines JButton-Objekts, das mit dem Bild

image versehen ist (horizontal rechtsbündig ausgerichtet)

public JButton(String text, Icon image) Erzeugung eines JButton-Objektsd, das mit dem Text

text beschriftet und mit dem Bild image versehen ist

public String getText() Rückgabe des dargestellten Textes

public Icon getIcon() Rückgabe des dargestellten Bildes

public void setText(String text) Setzen des darzustellenden Textes auf text

public void setIcon(Icon image) Setzen des darzustellenden Bildes auf image

public void setHorizontalAlignment(int halign) Setzen der horizontalen Ausrichtung

gemäß halign (für Text und Bild)

public void setVerticalAlignment(int valign) Setzen der vertikalen Ausrichtung

gemäß valign (für Text und Bild)

Page 31: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

31

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 566 – 00 – TH – 05

------------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (6)

Die Klasse JTextField (Package javax.swing)

◇ Diese Klasse ist von der abstrakten Basisklasse JTextComponent (Package javax.swing.text) abgeleitet.

Sie dient zur Erzeugung von editierbaren einzeiligen Textfeldern.

Die Editierbarkeit kann ein- und ausgeschaltet werden (Default nach Objekt-Erzeugung : eingeschaltet).

◇ JTextField-Objekte können sowohl zur Ausgabe als auch zur Eingabe (wenn die Editierbarkeit eingeschaltet ist)

von Text verwendet werden.

◇ Die Größe eines Textfeldes (= Anzahl der dargestellten Zeichenpositionen) kann kleiner (und natürlich auch größer)

als die Textlänge sein. Das heisst, dass auch Text eingegeben werden kann, desen Länge die Anzahl der darstellbaren

Positionen überschreitet.

◇ Die horizontale Ausrichtung des Textes innerhalb des dargestellten Zeilenfensters kann festgelegt werden.

Hierfür stehen die folgenden Konstanten zur Verfügung :

- JTextField.LEFT (linksbündig)

- JTextField.RIGHT (rechtsbündig)

- JTextField.CENTER (zentriert)

- JTextField.LEADING (Darstellung der führenden Zeichen, wenn Feldlänge kleiner als Textlänge, default)

- JTextField.TRAILING (Darstellung der Zeichen am Ende, wenn Feldlänge kleiner als Textlänge)

◇ Die Editierfunktionalität umfasst auch die Zusammenarbeit mit dem Clipboard : Text kann aus dem Clipboard einge-

fügt bzw im Textfeld markiert und – ausgeschnitten oder kopiert – in das Clipboard eingefügt werden.

◇ Konstruktoren (Auswahl)

◇ Memberfunktionen (Auswahl) Die meisten der nachfolgend aufgeführten Memberfunktionen sind von der Klasse JTextComponent geerbt.

*) geerbt von JTextComponent (Package javax.swing.text)

public JTextField() Erzeugung eines "leeren" JTextField-Objekts, die Feldgröße = 0

public JTextField(String text) Erzeugung eines JTextField-Objekts, das mit text initialisiert ist,

die Feldgröße wird durch die Länge von text bestimmt.

public JTextField(int cols) Erzeugung eines "leeren" JTextField-Objekts,

die Feldgröße ist durch cols festgelegt.

public JTextField(String text, Erzeugung eines JTextField-Objekts, das mit text initialisiert ist,

int cols) die Feldgröße ist durch cols festgelegt

public void setColumns(int cols) Setzen der Feldgröße auf cols, das Layout wird ungültig gesetzt

public String getText() *) Rückgabe des im Textfeld enthaltenen Textes

public String getSelectedText() *) Rückgabe des markierten Teils des im Textfeld enthaltenen Textes

public void setText(String text) *) Setzen des im Textfeld enthaltenen Textes auf text

public void setEditable(boolean b) Setzen / Aufheben der Editierbarkeit des Textfeldes gemäß b

*) b==true : Setzen der Editierbarkeit, andernfalls Aufheben

public boolean isEditable() *) Ermittelung der Editierbarkeit des Textfeldes

Rückgabewert ==true : editierbar, andernfalls nicht editierbar

public void setHorizontalAlignment(int halign) Setzen der horizontalen Ausrichtung des

Textfeldes auf halign

Page 32: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

32

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 567 – 01 – TH – 02

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (7-1)

Die Klasse JTextArea (Package javax.swing)

◇ Diese Klasse ist ebenfalls von der Klasse JTextComponent abgeleitet.

Sie dient zur Darstellung editierbarer mehrzeiliger Textfelder.

Wie bei der Klasse JTextField kann die Editierbarkeit ein- und ausgeschaltet werden (Default nach Objekt-

Erzeugung : eingeschaltet).

◇ JTextArea-Objekte können sowohl zur Ausgabe als auch zur Eingabe (bei eingeschalteter Editierbarkeit) von Text,

der mehrere Zeilen umfassen kann, eingesetzt werden.

Die Größe des im JTextArea-Objektes darzustellenden Textes kann sich damit dynamisch ändern.

◇ Auch bei dieser Klasse schliesst die Editierfunktionalität die Verwendung des Clipboards ein : Text kann aus dem Clip-

board eingefügt bzw im Textfeld markiert und – ausgeschnitten oder kopiert – in das Clipboard eingefügt werden.

◇ Die Klasse JTextArea stellt mehrere Methoden zur Verfügung, mit denen der dargestellte Text auch vom Programm

aus editiert werden kann.

U.a. existieren Methoden zum zeilenweisen Text-Zugriff sowie zum Einfügen und Anhängen von Text.

◇ Die Größe des im JTextArea-Objektes darzustellenden Textes kann sich infolge des benutzer-initiierten oder pro-

gramm-initiierten Editierens dynamisch ändern.

◇ Es ist möglich, für ein JTextArea-Objekt die Anzahl der Zeilen und Spalten festzulegen. Diese dienen zur Ermitt-

lung seiner bevorzugten Größe (preferred size), die aber nicht der Größe des tatsächlich dargestellten Textfensters

(Darstellungsbereich) entsprechen muß. Diese wird vielmehr durch den eingesetzten Layout-Manager gegebenenfalls

unter Berücksichtigung der Größe des umfassenden Containers festgelegt.

◇ Für den Fall, dass eine darzustellende Zeile länger als die dargestellte Textfenster-Breite ist, kann ein automatischer

Zeilenumbruch eingeschaltet werden

Bei eingeschalteten Zeilenumbruch kann festgelegt werden, ob ein Umbruch nach jedem Zeichen (zeichenweiser Um-

bruch) oder nur an einer Wortgrenze (wortweiser Umbruch) erfolgen kann.

Defaultmässig ist der Zeilenumbruch ausgeschaltet. Der nicht in das dargestellte Fenster passende Zeilenteil ist dann

nicht sichtbar.

Analoges gilt, wenn die tatsächliche Anzahl der darzustellenden Textzeilen größer als die durch das dargestellte Text-

fenster gegebene Zeilenzahl ist.

◇ JTextArea-Objekte besitzen keine Scroll-Fähigkeiten (Unterschied zu der AWT-Klasse TextArea).

Diese lassen sich aber durch das Einbetten eines JTextArea-Objektes in ein JScrollPane-Objekt realisieren.

In diesem Fall wird für den Scrollbereich die durch Zeilen- und Spaltenzahl festgelegte bevorzugte Größe berücksichtigt.

◇ Konstruktoren (Auswahl)

public JTextArea() Erzeugung eines "leeren" JTextArea-Objekts (Die Referenz auf den

enthaltenen String ist null)

Die Werte für die Anzahl der Zeilen und Spalten werden auf 0 gesetzt

public JTextArea(String text) Erzeugung eines JTextArea-Objekts, das mit text initialisiert ist,

Die Werte für die Anzahl der Zeilen und Spalten werden auf 0 gesetzt

public JTextArea(int rows, Erzeugung eines "leeren" JTextArea-Objekts,

int cols) Die Anzahl der Zeilen ist durch rows, die Anzahl der Spalten durch

cols festgelegt.

public JTextArea(String text, Erzeugung eines JTextArea-Objekts, das mit text initialisiert ist,

int rows, Die Anzahl der Zeilen ist durch rows, die Anzahl der Spalten durch

int cols) cols festgelegt.

Page 33: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

33

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 567 – 02 – TH – 02

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (7-2)

Die Klasse JTextArea (Package javax.swing), Forts.

◇ Memberfunktionen (Auswahl) Wie in der Klasse JTextField werden zahlreiche Memberfunktionen von der Klasse JTextComponent geerbt.

Zusätzlich definiert die Klasse JTextArea eine Reihe eigener Methoden

*) geerbt von JTextComponent (Package javax.swing.text)

public String getText() *) Rückgabe des im Textfeld enthaltenen Textes

public String getSelectedText() *) Rückgabe des markierten Teils des im Textfeld enthaltenen Textes

public void setText(String text) *) Setzen des im Textfeld enthaltenen Textes auf text

public void setEditable(boolean b) Setzen / Aufheben der Editierbarkeit des Textfeldes gemäß b

*) b==true : Setzen der Editierbarkeit, andernfalls Aufheben

public boolean isEditable() *) Ermittlung der Editierbarkeit des Textfeldes

Rückgabewert ==true : editierbar, andernfalls nicht editierbar

public void setRows(int rows) Setzen der Anzahl Zeilen auf rows

public void setColumns(int cols) Setzen der Anzahl Spalten auf cols

public int getRows() Ermittlung der festgelegten Zeilen-Anzahl

public int getColumns() Ermittlung der festgelegten Spalten-Anzahl

public int getLineCount() Ermittlung der tatsächlich im Text vorhandenen Zeilenzahl

public void setLineWrap(boolean b) Setzen/Aufheben des automatischen Zeilenumbruchs gemäß b

b==true : Setzen des Zeilenumbruchs, andernfalls Aufheben

public boolean getLineWrap() Ermittlung, ob automatischer Zeilenumbruch gesetzt ist

Rückgabewert ==true : Zeilenumbruch ist gesetzt

public void setWrapStyleWord(boolean b) Setzen der Art des Zeilenumbruchs gemäß b

b==true : wortweiser Zeilenumbruch

b==false : zeichenweiser Zeilenumbruch (Default)

public boolean getWrapStyleWord() Ermittlung der Art des Zeilenumbruchs

Rückgabewert ==true : wortweiser Zeilenumbruch

Rückgabewert ==false : zeichenweiser Zeilenumbruch

void append(String str) Anhängen des Strings str an das Ende des dargestellten Textes

void insert(String str, int pos) Einfügen des Strings str an der Position pos im Text

void replaceRange(String str, Ersetzen des Textes zwischen den Positionen beg und end

int beg, int end) durch den String str

Page 34: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

34

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 567 – 03 – TH – 01

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (7-3)

Demonstrationsprogramm zur Klasse JTextArea (JTextAreaDemo)

// JTextAreaDemo.java

import java.awt.*;

import javax.swing.*;

import java.io.*;

public class JTextAreaDemo extends JFrame

{

private final static String DEF_FILE_NAME = "schlechterwitz.txt";

private Container c;

private JTextField tf;

private JTextArea ta;

public JTextAreaDemo(String dname)

{ super("JTextAreaDemo");

tf = new JTextField("Inhalt der Datei \"" + dname + '\"');

tf.setHorizontalAlignment(JTextField.CENTER);

tf.setFont(new Font("SansSerif", Font.BOLD, 14));

tf.setBackground(Color.YELLOW);

c=getContentPane();

ta = new JTextArea(20, 50);

if (dname!=null)

fillTextAreaFromFile(dname);

ta.setFont(new Font("SansSerif", Font.PLAIN, 13));

//ta.setLineWrap(true); // Setzen des automatischen Zeilenumbruchs

//ta.setWrapStyleWord(true); // Setzen der Umbruchsart auf wortweise

c.add(tf, BorderLayout.NORTH);

c.add(ta);

setSize(360, 270);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

private void fillTextAreaFromFile(String dname)

{ try

{ BufferedReader bfr = new BufferedReader(new FileReader(dname));

String line;

while ((line=bfr.readLine()) != null)

ta.append(line + '\n');

bfr.close();

}

catch(IOException ex)

{ System.out.println("Exception " + ex.getMessage());

}

}

public static void main(String[] args)

{ String fname;

if (args.length==0)

fname = DEF_FILE_NAME;

else

fname = args[0];

new JTextAreaDemo(fname).setVisible(true);

}

}

Page 35: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

35

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 567 – 04 – TH – 01

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (7-4)

Ausgabe des Demonstrationsprogramms zur Klasse JTextArea (JTextAreaDemo)

◇ Automatischer Zeilenumbruch nicht gesetzt (default)

◇ Automatischer Zeilenumbruch gesetzt (zeichenweiser Umbruch)

◇ Automatischer Zeilenumbruch gesetzt (wortweiser Umbruch)

Page 36: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

36

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 568 – 01 – TH – 03

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (8-1)

Die Klasse JScrollPane (Package javax.swing)

◇ Objekte dieser Klasse dienen zur Einbettung anderer GUI-Komponenten in einen scrollbaren Darstellungsbereich.

Statt die GUI-Komponente direkt in einen Container einzufügen, wird sie in ein JScrollPane-Objekt eingebettet

und dieses dann in den Container eingefügt.

◇ JScrollPane-Objekte verwalten einen Darstellungsbereich (viewport), in dem die eingebettete GUI-Komponente

eingeblendet wird. Wenn die eingebettete Komponente größer als der zur Verfügung stehende Darstellungsbereich ist, wird sie nur aus-

schnittsweise angezeigt. Mit Hilfe von zwei Schiebereglern (scroll bars, horizontale und vertikale Bildlaufleiste) kann

der dargestellte Ausschnitt dynamisch verändert werden.

◇ Es kann festgelegt werden, wann die Bildlaufleisten sichtbar sein sollen (Scroll Bar Policy) :

▻ nur sichtbar, wenn nötig (default)

▻ immer sichtbar

▻ nie sichtbar Dies kann – getrennt für die vertikale und horizontale Bildlaufleiste – im Konstruktor bei der JScrollPane-Objekt-

Erzeugung oder später mittels spezieller Memberfunktionen erfolgen. Zur Festlegung stehen die folgenden – im implementierten Interface ScrollPaneConstants (Package

javax.swing) definierten – Konstanten zur Verfügung :

- JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED (vertikale Bildlaufleiste nur bei Bedarf sichtbar)

- JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED (horizontale Bildlaufleiste nur bei Bedarf sichtbar)

- JScrollPane.VERTICAL_SCROLLBAR_ALWAYS (vertikale Bildlaufleiste immer sichtbar)

- JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS (horizontale Bildlaufleiste immer sichtbar)

- JScrollPane.VERTICAL_SCROLLBAR_NEVER (vertikale Bildlaufleiste nie sichtbar)

- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER (horizontale Bildlaufleiste nie sichtbar)

◇ Prinzipiell kann jede beliebige GUI-Komponente in ein JScrollPane-Objekt eingebettet werden.

Diese kann im Konstruktor angegeben oder mittels einer entsprechenden Memberfunktion festgelegt werden.

◇ Für ein JScrollPane-Objekt können zusätzlich ein Zeilen-Header, ein Spalten-Header und Eck-Komponenten

festgelegt werden.

◇ Konstruktoren (Auswahl)

◇ Memberfunktionen (Auswahl)

public JScrollPane() Erzeugung eines "leeren" JScrollPane-Objekts.

Beide Bildlaufleisten werden nur bei Bedarf dargestellt

public JScrollPane(Component view) Erzeugung eines JScrollPane-Objekts, in dem das GUI-

Komponenten-Objekt view eingebettet ist.

Beide Bildlaufleisten werden nur bei Bedarf dargestellt

public JScrollPane(Component view, Erzeugung eines JScrollPane-Objekts, in dem das GUI-

int vsbPol, int hsbPol) Komponenten-Objekt view eingebettet ist

Die Sichtbarkeit der Bildlaufleisten wird durch vsbPol (verti-

kal und hsbPol (horizontal) festgelegt

public void setVerticalScrollBarPolicy(int pol) Setzen der ScrollBarPolicy für die vertikale

Bildlaufleiste auf pol

public void setHorizontalScrollBarPolicy(int pol) Setzen der ScrollBarPolicy für die horizontale

Bildlaufleiste auf pol

public void setViewportView(Component view) Einbettung des GUI-Komponenten-Objekts view

Page 37: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

37

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 568 – 02 – TH – 01

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (8-2)

Demonstrationsprogramm zur Klasse JScrollPane (JScrollPaneDemo)

// JScrollPaneDemo.java

// Einbettung eines JTextArea-Objekts in ein JScrollPane-Objekt

// Modifikation des Demonstrations-Programms zur Klasse JTextArea

import java.awt.*;

import javax.swing.*;

import java.io.*;

public class JScrollPaneDemo extends JFrame

{

final static String DEF_FILE_NAME = /*"beispiel.txt"*/"schlechterwitz.txt";

private Container c;

private JTextField tf;

private JTextArea ta;

private JScrollPane sp;

public JScrollPaneDemo(String dname)

{ super("JScrollPaneDemo");

tf = new JTextField("Inhalt der Datei \"" + dname + '\"');

tf.setHorizontalAlignment(JTextField.CENTER);

tf.setFont(new Font("SansSerif", Font.BOLD, 14));

tf.setBackground(Color.YELLOW);

c=getContentPane();

ta = new JTextArea(20,50);

if (dname!=null)

fillTextAreaFromFile(dname);

ta.setFont(new Font("SansSerif", Font.PLAIN, 13));

sp = new JScrollPane(ta);

c.add(tf, BorderLayout.NORTH);

c.add(sp);

setSize(380, 250);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

private void fillTextAreaFromFile(String dname)

{ try

{ BufferedReader bfr = new BufferedReader(new FileReader(dname));

String line;

while ((line=bfr.readLine()) != null)

ta.append(line + '\n');

bfr.close();

}

catch(IOException ex)

{ System.out.println("Exception " + ex.getMessage());

}

}

public static void main(String[] args)

{

String fname;

if (args.length==0)

fname = DEF_FILE_NAME;

else

fname = args[0];

new JScrollPaneDemo(fname).setVisible(true);

}

}

Page 38: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

38

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 568 – 03 – TH – 01

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (8-3)

Ausgabe des Demonstrationsprogramms zur Klasse JScrollPane (JScrollPaneDemo)

◇ Automatischer Zeilenumbruch für das eingebettete JTextArea-Objekt nicht gesetzt (default)

◇ Automatischer Zeilenumbruch für das eingebettete JTextArea-Objekt gesetzt (wortweiser Umbruch)

◇ Automatischer Zeilenumbruch für das eingebettete JTextArea-Objekt nicht gesetzt (default)

Page 39: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

39

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 568 – 04 – TH – 02

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (8-4)

Weiteres Demonstrationsprogramm zur Klasse JScrollPane (JScrollPaneDemo2)

// JScrollPaneDemo2.java

// Einbettung eines JButton-Objekts mit einem Bild in ein JScrollPane-Objekt

import java.awt.*;

import javax.swing.*;

import java.io.*;

public class JScrollPaneDemo2 extends JFrame

{

final static String DEF_FILE_NAME = "UnixCountry.jpg";

private Container c;

private JButton but; // alternativ : JLabel but;

private JTextField tf;

private JScrollPane sp;

public JScrollPaneDemo2(String dname)

{ super("JScrollPaneDemo2");

tf = new JTextField("Inhalt der Datei \"" + dname + '\"');

tf.setHorizontalAlignment(JTextField.CENTER);

tf.setFont(new Font("SansSerif", Font.BOLD, 14));

tf.setBackground(Color.YELLOW);

c=getContentPane();

Icon pict = new ImageIcon(dname);

but = new JButton(pict); // alternativ : but = new JLabel(pict);

sp = new JScrollPane(but);

c.add(tf, BorderLayout.NORTH);

c.add(sp);

setSize(550, 350);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

public static void main(String[] args)

{ String fname;

if (args.length==0)

fname = DEF_FILE_NAME;

else

fname = args[0];

new JScrollPaneDemo2(fname).setVisible(true);

}

}

Page 40: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

40

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 568 – 05 – TH – 01

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (8-5)

Ausgabe des weiteren Demonstrationsprogramms zur Klasse JScrollPane (JScrollPaneDemo2)

◇ verschiedene Stellungen der Schieberegler (Bildlaufleiste)

Page 41: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

41

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 569 – 00 – TH – 02

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (9)

Die Klasse JCheckBox (Package javax.swing)

◇ Diese Klasse dient zur Erzeugung von Auswahlfeldern.

Ein Auswahlfeld (check box) ist ein kleines Kästchen, das bei der Anwahl selektiert und deselektiert werden kann.

Der jeweilige Selektionszustand wird angezeigt :

De-selektiert ist das Kästchen leer, selektiert enthält es einen kleinen Haken.

◇ Ein JCheckBox-Objekt dient i.a. zur Darstellung eines logischen Wertes (boolean) auf einer GUI-Oberfläche.

◇ In einer Gruppe von JCheckBox-Objekten (Auswahlfeldern) können beliebig viele selektiert sein

◇ Ein JCheckBox-Objekt kann mit einem Text beschriftet oder/und mit einem Bild versehen werden.

Ein Bild ersetzt dabei das Auswahlfeld-Kästchen in der Darstellung. Eine eventuelle Selektion kann dann optisch nicht

mehr erkannt werden.

◇ Die Klasse ist von der Klasse JToggleButton abgeleitet, die ihrerseits die abstrakte Klasse AbstractButton

als direkte Basisklasse hat.

◇ Konstruktoren (Auswahl)

◇ Memberfunktionen : Ein großer Teil der angebotenen Schnittstelle ist von der Klasse AbstractButton geerbt,

u.a. :

public JCheckBox() Erzeugung eines nicht selektierten JCheckBox-Objekts

ohne Text und ohne Bild

public JCheckBox(String text) Erzeugung eines nicht selektierten JCheckBox-Objekts,

mit dem Text text beschriftet

public JCheckBox(String text, Erzeugung eines JCheckBox-Objekts, dessen Anfangs-

boolean select) Selektionszustand durch select festgelegt ist

(select==true : selektiert), Beschriftung mit Text text

public JCheckBox(Icon image) Erzeugung eines nicht selektierten JCheckBox-Objekts,

mit dem Bild image versehen

public JCheckBox(Icon image, Erzeugung eines JCheckBox-Objekts, dessen Anfangs-

boolean select) Selektionszustand durch select festgelegt ist

(select==true : selektiert), mit dem Bild image versehen

public JCheckBox(String text, Erzeugung eines nicht selektierten JCheckBox-Objekts,

Icon image) mit dem Text text beschriftet und dem Bild image versehen

public JCheckBox(String text, Erzeugung eines JCheckBox-Objekts, dessen Anfangs-

Icon image, Selektionszustand durch select festgelegt ist

boolean select) (select==true : selektiert), mit dem Text text beschriftet

und mit dem Bild image versehen

public void setSelected(boolean b) Setzen des Selektionszustands gemäß b

b==true : selektiert, andernfalls nicht selektiert

public boolean isSelected() Ermittlung des Selektionszustands

Rückgabewert ==true : selektiert,

==false : nicht selektiert

Page 42: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

42

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 56A – 01 – TH – 04

------------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (10-1)

Die Klasse JRadioButton (Package javax.swing)

◇ Diese Klasse dient ebenfalls zur Erzeugung von Auswahlfeldern.

JRadioButton-Objekte können somit auch zur Darstellung logischer Werte (boolean) auf einer GUI-Oberfläche

eingesetzt werden.

◇ Im Unterschied zur Klasse JCheckBox werden aber mehrere JRadioButton-Objekte meist so zu einer Gruppe

zusammengefasst, dass immer nur ein Auswahlfeld aus der Gruppe selektiert werden soll (und kann) (Gruppe alter-

nativer Auswahlfelder).

◇ Ein Auswahlfeld der Klasse JRadioButton wird durch einen kleinen Kreis dargestellt. Im unselektierten Zustand

ist der Kreis leer, bei Selektion erscheint ein Punkt im Kreis.

◇ Die Klasse JRadioButton ist ebenfalls von der Klasse JToggleButton und damit auch von der abstrakten

Klasse AbstractButton abgeleitet.

◇ Auch ein JRadioButton-Objekt kann mit einem Text beschriftet oder/und mit einem Bild versehen werden.

Ein Bild ersetzt dabei den Auswahlfeld-Kreis in der Darstellung. Eine eventuelle Selektion kann dann optisch nicht

mehr erkannt werden.

◇ Konstruktoren (Auswahl)

◇ Memberfunktionen : Die angebotene Schnittstelle entspricht weitgehend – soweit sie von der Klasse AbstractButton geerbt ist –

der Schnittstelle der Klasse JCheckBox.

U.a. stehen somit auch die folgenden Methoden zur Verfügung :

public JRadioButton() Erzeugung eines nicht selektierten JRadioButton-Objekts

ohne Text und ohne Bild

public JRadioButton (String text) Erzeugung eines nicht selektierten JRadioButton -Objekts,

mit dem Text text beschriftet

public JRadioButton (String text, Erzeugung eines JRadioButton -Objekts, dessen Anfangs-

boolean select) Selektionszustand durch select festgelegt ist

(select==true : selektiert), Beschriftung mit Text text

public JRadioButton (Icon image) Erzeugung eines nicht selektierten JRadioButton -Objekts,

mit dem Bild image versehen

public JRadioButton (Icon image, Erzeugung eines JRadioButton -Objekts, dessen Anfangs-

boolean select) Selektionszustand durch select festgelegt ist

(select==true : selektiert), mit dem Bild image versehen

public JRadioButton (String text, Erzeugung eines nicht selektierten JRadioButton -Objekts,

Icon image) mit dem Text text beschriftet und dem Bild image versehen

public JRadioButton (String text, Erzeugung eines JRadioButton -Objekts, dessen Anfangs-

Icon image, Selektionszustand durch select festgelegt ist

boolean select) (select==true : selektiert), mit dem Text text beschriftet

und mit dem Bild image versehen

public void setSelected(boolean b) Setzen des Selektionszustands gemäß b

b==true : selektiert, andernfalls nicht selektiert

public boolean isSelected() Ermittlung des Selektionszustands

Rückgabewert ==true : selektiert,

==false : nicht selektiert

Page 43: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

43

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 56A – 02 – TH – 03

------------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (10-2)

Die Klasse ButtonGroup (Package javax.swing)

◇ Objekte dieser Klasse dienen zur logischen Zusammenfassung mehrerer JRadioButton-Objekte zu einer Gruppe,

in der immer nur ein Objekt selektiert werden kann.

◇ Sie stellen selbst keine GUI-Komponenten dar und erscheinen deshalb auch nicht auf der GUI-Oberfläche.

◇ Nach der Erzeugung eines ButtonGroup-Objekts und dem Hinzufügen der JRadioButton-Objekte, die zusam-

mengefasst werden sollen, sind alle JRadioButton-Objekte zunächst de-selektiert.

Nach der erstmaligen Selektion eines JRadioButton-Objekts ist immer genau ein Objekt der Gruppe selektiert.

Es gibt danach keine Möglichkeit mehr, alle Objekte gleichzeitig in den de-selektierten Zustand zu versetzen.

◇ Konstruktor :

◇ Memberfunktionen :

◇ Anmerkung :

▻ Genaugenommen können durch ein ButtonGroup-Objekt nicht nur JRadioButton-Objekte sondern Objekte

jeder von AbstractButton abgeleiteten Klasse zusammengefasst werden (Parameter von add() !!!).

Allerdings ist eine derartige Zusammenfassung nicht immer sinnvoll.

▻ Beispielsweise lassen sich auch JCheckBox-Objekte derartig zu einer Gruppe zusammenfassen. Diese Gruppe

ver hält sich dann wie eine JRadioButton-Gruppe (nur eine Checkbox kann jeweils alternativ selektiert werden),

was aber der typischen Anwendung von JCheckBox-Objekten wiederspricht.

▻ Bei Objekten einiger von AbstractButton abgeleiteten Klassen (z.B. JButton und JMenuItem) macht

die Zusammenfassung zu einer Gruppe schon deshalb keinen Sinn, weil sie den jeweiligen Selektionszustand nicht

anzeigen.

public ButtonGroup() Erzeugung eine neuen ButtonGroup-Objekts

public void add(AbstractButton b) Hinzufügen des Buttons (konkret JRadioButton-Objekts) b

zur Gruppe

public void remove(AbstractButton b) Entfernen des Buttons (konkret JRadioButton-Objekts) b

aus der Gruppe

public int getButtonCount() Rückgabe der Anzahl in der Gruppe enthaltenen

AbstractButton-(konkret JRadioButton-)Objekte

public Enumeration<AbstractButton> Rückgabe aller in der Gruppe enthaltenen AbstractButton-

getElements() (konkret JRadioButton-)Objekte

Page 44: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

44

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 56A – 03 – TH – 01

-----------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (10-3)

Demonstrationsprogramm zu den Klassen JCheckBox und JRadioButton

// AuswahlfeldDemo.java

import java.awt.*;

import javax.swing.*;

public class AuswahlfeldDemo extends JFrame

{

private Container c;

private JCheckBox[] cba;

private JRadioButton[] rba;

public AuswahlfeldDemo(int anz)

{

setTitle("AuswahlfeldDemo");

c = getContentPane();

c.setLayout(new GridLayout(2,0));

cba = new JCheckBox[anz];

for (int i=0; i<cba.length; i++)

{

cba[i] = new JCheckBox("Auswahl " + (i+1));

c.add(cba[i]);

}

rba = new JRadioButton[anz];

ButtonGroup bg = new ButtonGroup();

for (int i=0; i<rba.length; i++)

{

rba[i] = new JRadioButton("Select " + (i+1));

bg.add(rba[i]);

c.add(rba[i]);

}

setSize(380, 120);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

public static void main(String[] args)

{

new AuswahlfeldDemo(4).setVisible(true);

}

}

Page 45: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

45

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 56B – 01 – TH – 05

------------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (11-1)

Die Klasse JPanel (Package javax.swing)

◇ Diese Klasse dient zur Erzeugung von Gruppierungsfeldern.

Ein Gruppierungsfeld ist ein "innerer" Container, der in erster Linie zur strukturierten Gestaltung des Inhalts von

Fensterbereichen dient.

Mit einem Gruppierungsfeld lassen sich mehrere Komponenten zu einer Komponente zusammenfassen, die dann wie-

derum in einen anderen Container (Top-Level-Container oder ein weiterer "innerer" Container) eingefügt werden kann.

◇ Die Klasse JPanel ist von der Klasse JComponent abgeleitet.

◇ Wie andere Container auch, verwenden JPanel-Objekte einen Layout-Manager. Im Unterschied zu den Top-Level-

Containern ist bei ihnen Flow-Layout als Default eingestellt.

Ein anderes Layout lässt sich gegebenenfalls bei der Objekt-Erzeugung im Konstruktor oder mittels der – von der

Klasse Container geerbten – Methode setLayout() setzen. Allerdings ist ein Setzen des BoxLayouts bei der Objekterzeugung ist nicht möglich.

Die folgende Anweisung JPanel mpan = new JPanel(new BoxLayout(mpan, BoxLayout.Y_AXIS));

führt zur der Compiler-Fehlermeldung "Variable mpan ist nicht initialisiert worden".

◇ JPanel-Objekte verfügen von Haus aus über keine Umrandung.

Bei Bedarf lassen sich aber Umrandungen mit der von der Klasse JComponent geerbten Methode setBorder()

setzen.

◇ Konstruktoren (Auswahl)

◇ Memberfunktionen

Die Klasse JPanel stellt die Methoden ihrer direkten und indirekten Basisklassen JComponent, Container

und Component zur Verfügung.

Sie fügt nur wenige weitere – für die Anwendung i.a. nicht wesentliche – Methoden hinzu.

public JPanel() Erzeugung eines JPanel-Objekts

(Flow-Layout voreingestellt)

public JPanel(LayoutManager layout) Erzeugung eines JPanel-Objekts mit dem durch layout

festgelegten Layout-Manager

Page 46: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

46

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 56B – 02 – TH – 03

------------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (11-2)

Demonstrationsprogramm zur Klasse JPanel

import java.awt.*;

import javax.swing.*;

import javax.swing.border.*;

public class JPanelDemo extends JFrame

{ Container c;

JPanel pan1, pan2, pan3;

public JPanelDemo()

{ super("JPanelDemo");

c=getContentPane();

pan1 = new JPanel();

pan2 = new JPanel();

pan3 = new JPanel(new GridLayout(2,3));

for (int i=1; i<=4; i++)

pan1.add(new JButton("Button " + i));

pan1.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));

pan1.setBackground(Color.ORANGE);

Icon javaLogo = new ImageIcon("javalogo52x88.gif");

JLabel lab1 = new JLabel(javaLogo);

JLabel lab2 = new JLabel("Java", SwingConstants.LEFT);

lab2.setBorder(BorderFactory.createEmptyBorder(0,0,0,30));

JLabel lab3 = new JLabel("avaJ", SwingConstants.RIGHT);

lab3.setBorder(BorderFactory.createEmptyBorder(0,30,0,0));

pan2.add(lab2); pan2.add(lab1); pan2.add(lab3);

for (int i=1; i<=6; i++)

pan3.add(new JCheckBox("Auswahl " + i));

Border bord1 = BorderFactory.createLineBorder(Color.GREEN, 5);

Border bord2 = BorderFactory.createTitledBorder(bord1, "Auswahl");

pan3.setBorder(bord2);

c.add(pan1, BorderLayout.NORTH);

c.add(pan2, BorderLayout.CENTER);

c.add(pan3, BorderLayout.SOUTH);

setSize(380, 270);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

public static void main(String[] args)

{ new JPanelDemo().setVisible(true);

}

}

Page 47: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

47

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 56C – 01 – TH – 01

------------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (12-1)

Die Klasse Box (Package javax.swing)

◇ Diese – direkt von JComponent abgeleitete – Klasse ist eine weitere "innere" Container-Klasse. Sie dient eben-

falls zur Erzeugung von Gruppierungsfeldern.

◇ Defaultmässig ist Box-Layout eingestellt. Dieses Layout kann jedoch nicht verändert werden

Die – indirekt von Container geerbte – Methode setLayout(...) ist so überschrieben, dass sie immer eine

AWTError-Exception wirft.

Gruppierungs-Box.

◇ Die Anordnungs-Achse des verwendeten Box-Layouts (vertikal oder horizontal) ist bei der Objekt-Erzeugung

anzugeben.

◇ Bezüglich der Verwendung als Gruppierungsfelder können Box-Objekte im wesentlichen wie JPanel-Objekte

eingesetzt werden.

Auch Box-Objekte verfügen von Haus aus über keine Umrandung. Mittels der von JComponent geerbten

Methode setBorder(...) lassen sich jederzeit gewünschte Umrandungen setzen.

◇ Als zusätzliche Besonderheit stellt die Klasse Box eine Reihe von statischen Methoden zur Verfügung, mit denen

unsichtbare GUI-Komponenten erzeugt werden können, die sich als Abstands- und Füll-Komponenten im Box-

Layout – auch in Nicht-Box-Containern – einsetzen lassen.

Diese Komponenten sind Objekte der Klasse Box.Filler (innere Klasse von Box), die ebenfalls direkt von der

Klasse JComponent abgeleitet ist.

Prinzipiell können diese Komponenten auch in anderen Layouts verwendet werden, aber ihre wesentliche Bedeutung

haben sie beim BoxLayout.

◇ Konstruktor

◇ Statische Methoden zur Objekterzeugung

◇ Statische Methoden zur Erzeugung unsichtbarer GUI-Komponenten (Auswahl)

public Box(int axis) Erzeugung eines Box-Objekts dessen Layout, die durch axis festgelegte

Anordnungs-Achse besitzt.

Folgende Konstante sind zulässige Werte für axis :

- BoxLayout.X_AXIS (horizontale Anordnung, in einer Zeile)

- BoxLayout.Y_AXIS (vertikale Anordnung, in einer Spalte)

- BoxLayout.LINE_AXIS (für europäische Sprachen : horizontale Anordnung)

- BoxLayout.PAGE_AXIS (für europäische Sprachen : vertikale Anordnung)

public static Box createHorizontalBox() Erzeugung eines Box-Objekts mit horizontaler

Anordnungs-Achse seines Layouts

public static Box createVerticalBox() Erzeugung eines Box-Objekts mit vertikaler

Anordnungs-Achse seines Layouts

public static Component createRigidArea(Dimension d) Erzeugung eines Box.Filler-Objekts

das die durch d definierte feste Grösse

besitzt ( Abstands-Komponente)

public static Component createHorizontalGlue() Erzeugung eines Box.Filler-Objekts variabler

anpassbarer Breite ( horizontale Füll-Komponente)

public static Component createVerticalGlue() Erzeugung eines Box.Filler-Objekts variabler

anpassbarer Höhe ( vertikale Füll-Komponente)

Page 48: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

48

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 56C – 03 – TH – 01

------------------------------------------------------------------------------------

Ausgewählte Swing-Komponenten-Klassen (12-3)

Demonstrationsprogramm zur Klasse Box (und zu unsichtbaren GUI-Komponenten)

import javax.swing.*;

import javax.swing.border.*;

import java.awt.*;

public class BoxDemo extends JFrame

{

public BoxDemo()

{ super("BoxDemo");

Box mbox = new Box(BoxLayout.Y_AXIS);

Box box1 = Box.createHorizontalBox(); // = new Box(BoxLayout.X_AXIS);

Box box2 = Box.createVerticalBox(); // = new Box(BoxLayout.Y_AXIS);

mbox.setBorder(BorderFactory.createLineBorder(Color.BLACK,3));

box1.setBorder(BorderFactory.createLineBorder(Color.GREEN,3));

box2.setBorder(BorderFactory.createLineBorder(Color.RED,3));

box1.setAlignmentX(CENTER_ALIGNMENT);

box2.setAlignmentX(CENTER_ALIGNMENT);

for (int i=1; i<=3; i++)

{ box1.add(Box.createRigidArea(new Dimension(5,0)));

box1.add(new JButton("HB-Button " + i));

}

box1.add(Box.createHorizontalGlue());

box1.setMinimumSize(new Dimension(400, 60));

box1.setMaximumSize(box1.getMinimumSize());

box1.setPreferredSize(box1.getMinimumSize());

box2.add(Box.createVerticalGlue());

for (int i=1; i<=2; i++)

{ box2.add(new JButton("VB-Button " + i));

box2.add(Box.createRigidArea(new Dimension(0,5)));

}

mbox.add(Box.createRigidArea(new Dimension(0,10)));

mbox.add(box1);

mbox.add(Box.createRigidArea(new Dimension(0,10)));

mbox.add(box2);

mbox.add(Box.createRigidArea(new Dimension(0,10)));

add(mbox, BorderLayout.CENTER);

setSize(480, 300);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

public static void main(String[] args)

{ new BoxDemo().setVisible(true);

}

}

Page 49: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

49

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 571 – 00 – TH – 02

------------------------------------------------------------------------------------

Ereignisverarbeitung in JFC-GUI-Komponenten (1)

Delegation Event Model

◇ In Programmen mit einem grafischen Benutzerinterface findet die Kommunikation zwischen dem Benutzer und dem

Programm mittels Ereignissen (events) statt.

◇ Benutzerinteraktionen mit der graphischen Oberfläche (wie z.B. Anwählen eines Schaltknopfes oder Auswahl eines

Menue-Eintrags mittels Maus oder Tastatur, Schliessen eines Fensters, sonstige Mausbewegungen und Mausklicks,

sonstige Tastatureingaben usw) lösen Ereignisse aus, die als Nachrichten vom Betriebssystem an das Programm gesandt

werden. Auch Änderungen der Größe, der Lage, des Inhalts und des sonstigen Zustands von GUI-Komponenten können

zu Ereignissen in diesem Sinne führen.

Ereignisse können also von unterschiedlichem Typ sein.

◇ Innerhalb eines Java-Programms werden die durch Nachrichten angezeigten Ereignisse als Objekte spezieller Ereignis-

Klassen (event objects) dargestellt.

Diese Ereignis-Objekte kapseln Informationen über das jeweilige Ereignis (z.B. die Ereignisquelle, spezielle Para-

meter, wie Mauskoordinaten, Tastaur-Codes usw)

◇ Die GUI-Komponente an der oder durch die ein Ereignis erzeugt wurde, wird als Ereignisquelle (event source)

bezeichnet. Prinzipiell kann jede Komponente einer graphischen Oberfläche eine derartige Ereignisquelle sein.

◇ Zuständig für die Reaktion auf das Ereignis sind spezielle Ereignisempfänger, die sogenannten Event-Listener.

Dies sind Objekte, die ein zum jeweiligen Ereignis passendes Bearbeitungs-Interface implementieren.

Damit ein Event-Listener-Objekt die von einer bestimmten Ereignisquelle verursachten Ereignisse empfangen kann,

muß es bei dieser Ereignisquelle als Listener registriert sein (Design Pattern Observer !).

Dabei werden einem Listener nur die Ereignisse mitgeteilt, die zu seinem Typ passen, d.h. für die er ein passendes

Bearbeitungs-Interface implementiert hat.

◇ Das Zustellen der einzelnen Ereignisse an die jeweils registrierten Event-Listener erfolgt durch den Aufruf der für den

Ereignis-Typ zuständigen Bearbeitungsfunktion des Listeners (Call Back !). Dieser wird das Ereignis-Objekt als Para-

meter übergeben.

In jedem GUI-Programm ist hierfür ein eigener Thread zuständig, der event-dispatching thread.

◇ Zwischen einer Ereignisquelle und einem Event-Listener muß keine 1:1-Beziehung bestehen.

Bei einer Ereignisquelle können durchaus mehrere Event-Listener registriert sein – sogar für den gleichen Ereignis-Typ.

Das Ereignis wird dann allen bei der Quelle für den jeweiligen Ereignis-Typ registrierten Event-Listenern zugestellt.

Andererseits kann ein Event-Listener auch gleichzeitig bei mehreren Ereignisquellen registriert sein.

◇ Das in Java seit dem JDK 1.1 implementierte Delegation Event Model wird sowohl für AWT-Komponenten als auch

Swing-Komponenten angewendet.

◇ Es ermöglicht eine klare Trennung zwischen dem Programmcode zur Oberflächengestaltung (GUI-Klassen !) und

dem Code zur Ereignisverarbeitung (Event-Listener-Klassen) als Schnittstelle zur Anwendungslogik.

Ereignisquelle 1 event Event-Listener 1

Ereignisquelle 2

Event-Listener 2

Event-Listener 3

event

Ereignisquelle 3

Event-Listener 4

event

event

Page 50: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

50

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 572 – 00 – TH – 03

------------------------------------------------------------------------------------

Ereignisverarbeitung in JFC-GUI-Komponenten (2)

Ereignis-Klassen

◇ Auszug aus der Hierarchie der Ereignisklassen

◇ Die verschiedenen Event-Klassen implementieren jeweils Memberfunktionen mit denen Informationen, die mit dem

jeweiligen Event-Objekt verknüpft sind, ermittelt werden können.

◇ Die Klasse EventObject, Basisklasse aller Ereignis-Klassen, stellt die folgende Methode zur Verfügung :

Diese Methode wird von allen anderen Ereignis-Klassen geerbt und kann damit für alle Event-Objekte aufgerufen

werden.

◇ Die verschiedenen Ereignis-Klassen sind jeweils bestimmten Ereignisse auslösenden Aktionen zugeordnet.

Beispielsweise wird ein ActionEvent-Objekt durch folgende Aktionen erzeugt :

- Betätigung eines Schaltknopfes

- Selektierung eines Auswahlfeldes

- Auswahl eines Menue- oder Auswahllisten-Eintrags

- Betätigung der RET-Taste

◇ In vielen Fällen kann bei einer Komponente einer bestimmten GUI-Klasse ein Objekt einer bestimmten Ereignis-Klasse

nur durch eine einzige Aktionsart erzeugt werden.

Diese Aktionsart kann bei den verschiedenen GUI-Klassen durchaus unterschiedlich sein.

Es gibt aber auch Ereignis-Klassen, die für mehrere verschiedene Aktionsarten bei der gleichen Komponente zuständig

sind.

Beispielsweise ist die Klasse MouseEvent sowohl für Mausbewegungen (mouse motion events) als auch für alle

sonstigen Mausereignisse (mouse events, wie Knopfbetätigung, Maus-Eintritt, Maus-Austritt in Komponente) zuständig

EventObject

(java.util)

AWTEvent

(java.awt)

ChangeEvent

(javax.swing.event)

ListSelectionEvent

(javax.swing.event)

CaretEvent

(javax.swing.event)

MenuEvent

(javax.swing.event)

ComponentEvent

(java.awt.event)

ActionEvent

(java.awt.event)

ItemEvent

(java.awt.event)

AncestorEvent

(javax.swing.event)

InputEvent

(java.awt.event)

ContainerEvent

(java.awt.event)

WindowEvent

(java.awt.event)

FocusEvent

(java.awt.event)

KeyEvent

(java.awt.event)

MouseEvent

(java.awt.event)

. . . weitere Event-

Klassen

. . . weitere Event-

Klassen

. . . weitere Event-

Klassen

AWT Swing

public Object getSource() Ermittlung der ursprünglichen Ereignisquelle

Page 51: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

51

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 573 – 00 – TH – 02

-----------------------------------------------------------------------------------

Ereignisverarbeitung in JFC-GUI-Komponenten (3)

Ereignis-Klassen, Forts.

◇ Da auf den verschiedenen GUI-Komponenten jeweils nur spezifische Aktionen ausgeführt werden können, können

diese auch nur Ereignisse ganz bestimmter Klassen auslösen.

Einige Ereignis-Klassen werden bereits in den Basisklassen der JFC-Hierarchie unterstützt. Entsprechende Ereignisse

können daher in allen Komponenten der davon abgeleiteten Klassen ausgelöst werden. Einige GUI-Komponenten und die von ihnen unterstützen Ereignis-Klassen :

◇ Memberfunktionen (Auswahl) einiger Ereignis-Klassen zur Informationsermittlung über das Ereignis :

▻ Klasse AWTEvent

▻ Klasse ActionEvent

▻ Klasse ItemEvent

▻ Klasse WindowEvent

public int getID() Ermittlung der auslösenden Aktionsart (Klassenkonstante !)

public String getActionCommand() Ermittlung der für das Ereignis festgelegten Aktionskennung

public Object getItem() Ermittlung des vom Ereignis betroffenen Objekts

public int getStateChange() Ermittlung des geänderten Zustands (selektiert oder nicht selektiert)

public Window getWindow() Ermittlung des Fensters, das das Ereignis ausgelöst hat

GUI-Klasse unterstützte Ereignis-Klasse auslösende Aktionn Component ComponentEvent Position, Größe oder Sichtbarkeit wurden geändert

FocusEvent Focus wurde erhalten oder verloren

KeyEvent Tastatur wurde betätigt

MouseEvent Maus wurde betätigt oder bewegt

Container ContainerEvent Container-Inhalt wurde verändert

Window WindowEvent Status des Fensters hat sich geändert

JComponent AncestorEvent Umgebender Container hat sich verändert

JButton ActionEvent Schaltknopf wurde betätigt

ChangeEvent Zustand des Schaltknopfes hat sich geändert

JTextField ActionEvent RET-Taste wurde betätigt

CaretEvent Cursorposition hat sich geändert

JTextArea CaretEvent Cursorposition hat sich geändert

JCheckBox ActionEvent Auswahlfeld wurde betätigt

und ChangeEvent Zustand des Auswahlfelds hat sich geändert

JRadioButton ItemEvent Selektionszustand hat sich geändert

JList ListSelectionEvent Selektion wurde geändert

Page 52: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

52

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 574 – 00 – TH – 03

-----------------------------------------------------------------------------------

Ereignisverarbeitung in JFC-GUI-Komponenten (4)

Listener-Interfaces

◇ Die beim Auftritt eines Ereignisses informierten Event-Listener müssen jeweils ereignisspezifisch reagieren können.

Ein Ereignis einer bestimmten Klasse kann nur ein Listener empfangen, der bestimmte zur Ereignis-Klasse passende

Reaktions-Methoden bereitstellt.

Jeder Listener muss ein bestimmtes Interface implementieren.

◇ Zu jeder Ereignis-Klasse ist mindestens ein passendes Listener-Interface definiert. Für einige Ereignis-Klassen gibt es

auch mehrere Listener-Interfaces. Allgemein gilt :

Zur Ereignis-Klasse AbcEvent existiert das Listener-Interface AbcListener.

Beispiele : Ereignisklasse ActionEvent Listener-Interface ActionListener

Ereignisklasse ItemEvent Listener-Interface ItemListener Bei mehreren mit einer Ereignis-Klasse korrespondierenden Listener-Interfaces gilt : Zur Ereignis-Klasse AbcEvent existieren Listener-Interfaces AbcXyzListener

Beispiel : Ereignis-Klasse WindowEvent Listener-Interface WindowListener

WindowFocusListener

WindowStateListener

◇ Die verschiedenen Interfaces sind definiert in den Packages java.awt.event und javax.swing.event.

Hierarchie der EventListener-Interfaces

◇ Alle Listener-Interfaces sind vom Interface EventListener (Package java.util) abgeleitet.

Dieses deklariert keine Methoden sondern ist ein reines Marker-Interface.

◇ Einige Interfaces deklarieren genau eine Methode. Sie sind i.a. sogenannten semantischen Ereignissen zugeordnet.

Andere Interfaces, die i.a. sogenannten Low-Level-Ereignissen zugeordnet sind, deklarieren mehrere Methoden.

Eine Event-Listener-Klasse muß alle Methoden des Interfaces, das sie implementiert, definieren.

Die jeweilige Methode enthält den vom Programm als Reaktion auf das Ereignis auszuführenden Code

( Event-Handler)

Die Information eines Event-Listeners über ein eingetretenes Ereignis erfolgt durch den Aufruf einer dieser Methoden

als Callback.

◇ Alle Methoden besitzen genau einen Parameter von der jeweiligen zugehörigen Ereignis-Klasse.

Page 53: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

53

Beim Aufruf einer Methode wird ihr das ausgelöste Ereignis-Objekt als aktueller Parameter übergeben.

◇ Einige Listener-Interfaces als Beispiele :

▻ Interface ActionListener (Package java.awt.event)

▻ Interface ItemListener (Package java.awt.event)

▻ Interface WindowListener (Package java.awt.event), unvollständig

public void actionPerformed(ActionEvent e) aufgerufen, wenn ein ActionEvent auftritt

public void itemStateChanged(ItemEvent e) aufgerufen, wenn ein ItemEvent auftritt

public void windowClosing(WindowEvent e) aufgerufen, wenn Fenster geschlossen werden soll

public void windowClosed(WindowEvent e) aufgerufen, wenn Fenster geschlossen wurde

public void windowActivated(WindowEvent e) aufgerufen, wenn Fenster aktiviert wurde

public void windowDeactivated(WindowEvent e) aufgerufen, wenn Fenster deaktiviert wurde

public void windowIconified(WindowEvent e) aufgerufen, wenn Fenster minimiert wurde

Page 54: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

54

Key-Events Unter Windows werden alle Tastatureingaben an die fokussierte Komponente gesendet. Ein Empfänger für Key-Events muß

das Interface KeyListener implementieren und bekommt Events des Typs KeyEvent übergeben. KeyEvent erweitert

die Klasse InputEvent, die ihrerseits aus ComponentEvent abgeleitet ist, und stellt neben getID und getSource

eine ganze Reihe von Methoden zur Verfügung, mit denen die Erkennung und Bearbeitung der Tastencodes vereinfacht wird.

Die Registrierung von Key-Events erfolgt mit der Methode addKeyListener, die auf allen Objekten des Typs

Component oder daraus abgeleiteten Klassen zur Verfügung steht:

public void addKeyListener(KeyListener l) java.awt.Component

Das Interface KeyListener definiert drei unterschiedliche Methoden:

public abstract void keyPressed(KeyEvent e)

public abstract void keyReleased(KeyEvent e)

public abstract void keyTyped(KeyEvent e)

Mouse-Events l Ein Mouse-Event entsteht, wenn der Anwender innerhalb der Client-Area des Fensters eine der Maustasten drückt oder

losläßt. Dabei reagiert das Programm sowohl auf Klicks der linken als auch - falls vorhanden - der rechten Maustaste und zeigt

an, welche der Umschalttasten [STRG], [ALT], [UMSCHALT] oder [META] während des Mausklicks gedrückt waren. Des

weiteren ist es möglich, zwischen einfachen und doppelten Mausklicks zu unterscheiden.

Ein Empfänger für Mouse-Events muß das Interface MouseListener implementieren und bekommt Events des Typs

MouseEvent übergeben. MouseEvent erweitert die Klasse InputEvent und stellt neben getID und getSource

eine Reihe zusätzlicher Methoden zur Verfügung, die wichtige Informationen liefern. Die Registrierung der Empfängerklasse

erfolgt mit der Methode addMouseListener, die in allen Klassen zur Verfügung steht, die aus Component abgeleitet

wurden: public void addMouseListener(MouseListener l)

Tabelle 29.3 gibt eine Übersicht der Methoden von MouseListener und erklärt ihre Bedeutung:

Ereignismethode Bedeutung

mousePressed Eine Maustaste wurde gedrückt.

mouseReleased Die gedrückte Maustaste wurde losgelassen.

mouseClicked Eine Maustaste wurde gedrückt und wieder losgelassen. Diese Methode wird nach

mouseReleased aufgerufen.

mouseEntered Der Mauszeiger wurde in den Client-Bereich der auslösenden Komponente hineinbewegt.

mouseExited Der Mauszeiger wurde aus dem Client-Bereich der auslösenden Komponente herausbewegt.

Page 55: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

55

FACHHOCHSCHULE MUENCHEN FAKULTÄT ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 575 – 00 – TH – 04

-----------------------------------------------------------------------------------

Ereignisverarbeitung in JFC-GUI-Komponenten (5)

Listener-Adapter-Klassen

◇ Eine Klasse, die ein Listener-Interface implementiert, dass mehrere Methoden deklariert, muss sämtliche Metho-

den definieren, auch wenn in der speziellen Anwendung nur eine von ihnen benötigt wird.

◇ Zur Vereinfachung der Definition von Listener-Klassen existieren für derartige Interfaces Adapter-Klassen.

Es handelt sich bei Ihnen um abstrakte Klassen, die sämtliche Methoden des Interfaces mit leerer Funktionalität

implementieren.

Statt eine Listener-Klasse das jeweilige Listener-Interface direkt implementieren zu lassen, leitet man die Klasse von

der zugehörigen Adapter-Klasse ab. Die Klasse muß dann lediglich die im konkreten Fall benötigte Methode über-

schreiben.

◇ Wenn zum Listener-Interface AbcListener eine Adapter-Klasse existiert, lautet ihr Name AbcAdapter. Beispiel : Listener-Interface WindowListener Listener-Adapter WindowAdapter

Listener-Klassen

◇ Sie müssen das Listener-Interface, das zu der Ereignis-Klasse, deren Objekte sie empfangen sollen, gehört, implemen-

tieren.

Eine Listener-Klasse kann auch mehrere Listener-Interfaces implementieren und damit auf Ereignisse unterschied-

licher Klassen reagieren.

◇ Eine Listener-Klasse kann das oder die Listener-Interfaces

▻ entweder direkt implementieren

▻ oder von einer zugehörigen Adapter-Klasse abgeleitet werden.

◇ Zur programmtechnischen Realisierung eine Listener-Klasse existieren folgende Möglichkeiten : (siehe Bspiele)

▻ Realisierung der Listener-Klasse als innere Klasse

▻ Realisierung der Listener-Klasse als lokale Klasse oder anonyme Klasse

▻ Realisierung der Listener-Klasse als Top-Level-Klasse

▻ Verwendung der Container-Klasse als Listener-Klasse

Implementierung einer Ereignisverarbeitung im Anwender-Code

◆ Definition einer geeigneten Event-Listener-Klasse.

In der (bzw den) zu implementierenden Interface-Methode(n) (Event-Handler) ist die Programmfunktionalität zu

realisieren, die als Reaktion auf den Eintritt eines Ereignisses der betreffenden Art vorgesehen ist.

◆ Erzeugung eines Objekts dieser Event-Listener-Klasse (Event-Listener-Objekt).

◆ Registrierung des Event-Listener-Objekts bei der auf Ereignisse zu "überwachenden" GUI-Komponente. Hierfür stellen die GUI-Komponenten für die von ihnen unterstützten Listener-Typen entsprechende Registrierungs-

funktionen zur Verfügung :

Für EventListener vom Typ AbcListener Funktion void addAbcListener(AbcListener lis) Beispiel : Klasse JButton für ActionListener-Objekte (geerbt von der Klasse AbstractButton) :

◆ Gegebenenfalls Festlegung von spezifischen Informationen, die einem Ereignis-Objekt übergeben werden. Beispiel : Klasse JButton : Setzen einer Aktionskennung (action command) für ActionListener-Objekte

(geerbt von der Klasse AbstractButton) :

public void addActionListener(ActionListener lis) Registrierung des Action-Listener-Objects lis

public void setActionCommand(String cmd) Setzen der Aktionskennung cmd

Page 56: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

56

Beispiele Variante 1: Implementierung eines EventListener-Interfaces Bei der ersten Variante gibt es nur eine einzige Klasse, Listing2802. Sie ist einerseits eine Ableitung der Klasse JFrame,

um ein Fenster auf dem Bildschirm darzustellen und zu beschriften. Andererseits implementiert sie das Interface

KeyListener, das die Methoden keyPressed, keyReleased und keyTyped definiert. Der eigentliche Code zur

Reaktion auf die Taste [ESC] steckt in der Methode keyPressed, die immer dann aufgerufen wird, wenn eine Taste

gedrückt wurde. Mit der Methode getKeyCode der Klasse KeyEvent wird auf den Code der gedrückten Taste zugegriffen

und dieser mit der symbolischen Konstante VK_ESCAPE verglichen. Stimmen beide überein, wurde [ESC] gedrückt, und das

Programm kann beendet werden.

001 /* Listing2802.java */

002

003 import java.awt.*;

004 import java.awt.event.*;

005

006 public class Listing2802

007 extends JFrame

008 implements KeyListener

009 {

010 public static void main(String[] args)

011 {

012 Listing2802 wnd = new Listing2802();

013 }

014

015 public Listing2802()

016 {

017 super("Nachrichtentransfer");

018 setBackground(Color.lightGray);

019 setSize(300,200);

020 setLocation(200,100);

021 setVisible(true);

022 addKeyListener(this);

023 }

024

025 public void paint(Graphics g)

026 {

027 g.setFont(new Font("Serif",Font.PLAIN,18));

028 g.drawString("Zum Beenden bitte ESC drücken...",10,50);

029 }

030

031 public void keyPressed(KeyEvent event)

032 {

033 if (event.getKeyCode() == KeyEvent.VK_ESCAPE) {

034 setVisible(false);

035 dispose();

036 System.exit(0);

037 }

038 }

039

040 public void keyReleased(KeyEvent event)

041 {

042 }

043

044 public void keyTyped(KeyEvent event)

045 {

046 }

047 }

Listing2802.java

Page 57: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

57

Listing 28.2: Implementieren eines Listener-Interfaces

Die Verbindung zwischen der Ereignisquelle (in diesem Fall der Fensterklasse Listing2802) und dem Ereignisempfänger

(ebenfalls die Klasse Listing2802) erfolgt über den Aufruf der Methode addKeyListener der Klasse JFrame. Alle

Tastaturereignisse werden dadurch an die Fensterklasse selbst weitergeleitet und führen zum Aufruf der Methoden

keyPressed, keyReleased oder keyTyped des Interfaces KeyListener. Diese Implementierung ist sehr

naheliegend, denn sie ist einfach zu implementieren und erfordert keine weiteren Klassen. Nachteilig ist dabei allerdings:

lEs besteht keine Trennung zwischen GUI-Code und Applikationslogik. Dies kann große Programme unübersichtlich

und schwer wartbar machen.

l Für jeden Ereignistyp muss eine passende Listener-Klasse registriert werden. Da viele der EventListener-

Interfaces mehr als eine Methode definieren, werden dadurch schnell viele leere Methodenrümpfe in der

Fensterklasse zu finden sein. In diesem Beispiel sind es schon keyReleased und keyTyped, bei zusätzlichen

Interfaces würden schnell weitere hinzukommen.

Es bleibt festzuhalten, dass diese Technik bestenfalls für kleine Programme geeignet ist, die nur begrenzt erweitert werden

müssen. Durch die Vielzahl leerer Methodenrümpfe können aber auch kleine Programme schnell unübersichtlich werden.

Variante 2: Lokale und anonyme Klassen Die zweite Alternative bietet eine bessere Lösung. Sie basiert auf der Verwendung lokaler bzw. anonymer Klassen und kommt

ohne die Nachteile der vorigen Version aus. Sie ist das in der Dokumentation des JDK empfohlene Entwurfsmuster für das

Event-Handling in kleinen Programmen oder bei Komponenten mit einfacher Nachrichtenstruktur. Vor ihrem Einsatz sollte

man allerdings das Prinzip lokaler und anonymer Klassen kennenlernen, das mit dem JDK 1.1 in Java eingeführt und in

Abschnitt 10.1 vorgestellt wurde. Wer diesen Abschnitt noch nicht gelesen hat, sollte das jetzt nachholen.

Lokale Klassen

Die Anwendung lokaler Klassen für die Ereignisbehandlung besteht darin, mit ihrer Hilfe die benötigten EventListener

zu implementieren. Dazu wird in dem GUI-Objekt, das einen Event-Handler benötigt, eine lokale Klasse definiert und aus

einer passenden Adapterklasse abgeleitet. Nun braucht nicht mehr das gesamte Interface implementiert zu werden (denn die

Methodenrümpfe werden ja aus der Adapterklasse geerbt), sondern lediglich die tatsächlich benötigten Methoden. Da die

lokale Klasse zudem auf die Membervariablen und Methoden der Klasse zugreifen kann, in der sie definiert wurde, lassen sich

auf diese Weise sehr schnell die benötigten Ereignisempfänger zusammenbauen.

Das folgende Beispiel definiert eine lokale Klasse MyKeyListener, die aus KeyAdapter abgeleitet wurde und auf diese

Weise das KeyListener-Interface implementiert. Sie überlagert lediglich die Methode keyPressed, um auf das Drücken

einer Taste zu reagieren. Als lokale Klasse hat sie außerdem Zugriff auf die Methoden der umgebenden Klasse und kann somit

durch Aufruf von setVisible und dispose das Fenster, in dem sie als Ereignisempfänger registriert wurde, schließen.

Die Registrierung der lokalen Klasse erfolgt durch Aufruf von addKeyListener, bei dem gleichzeitig eine Instanz der

lokalen Klasse erzeugt wird. Als lokale Klasse ist MyKeyListener überall innerhalb von Listing2803 sichtbar und kann

an beliebiger Stelle instanziert werden.

001 /* Listing2803.java */

002

003 import java.awt.*;

004 import java.awt.event.*;

import javax.swing.*;

005

006 public class Listing2803

007 extends JFrame

008 {

009 public static void main(String[] args)

010 {

011 Listing2803 wnd = new Listing2803();

012 }

013

014 public Listing2803()

015 {

016 super("Nachrichtentransfer");

017 setBackground(Color.lightGray);

018 setSize(300,200);

019 setLocation(200,100);

020 setVisible(true);

021 addKeyListener(new MyKeyListener());

022 }

023

Page 58: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

58

024 public void paint(Graphics g)

025 {

026 g.setFont(new Font("Serif",Font.PLAIN,18));

027 g.drawString("Zum Beenden bitte ESC drücken...",10,50);

028 }

029

030 class MyKeyListener

031 extends KeyAdapter

032 {

033 public void keyPressed(KeyEvent event)

034 {

035 if (event.getKeyCode() == KeyEvent.VK_ESCAPE) {

036 setVisible(false);

037 dispose();

038 System.exit(0);

039 }

040 }

041 }

042 }

Listing 28.3: Verwendung lokaler Klassen

Der Vorteil dieser Vorgehensweise ist offensichtlich: es werden keine unnützen Methodenrümpfe erzeugt, aber trotzdem

verbleibt der Ereignisempfängercode wie im vorigen Beispiel innerhalb der Ereignisquelle. Dieses Verfahren ist also immer

dann gut geeignet, wenn es von der Architektur oder der Komplexität der Ereignisbehandlung her sinnvoll ist, Quelle und

Empfänger zusammenzufassen.

Anonyme Klassen Das folgende Beispiel ist eine leichte Variation des vorigen. Es zeigt die Verwendung einer anonymen Klasse, die aus

KeyAdapter abgeleitet wurde, als Ereignisempfänger. Zum Instanzierungszeitpunkt erfolgt die Definition der überlagernden

Methode keyPressed, in der der Code zur Reaktion auf das Drücken der Taste [ESC] untergebracht wird.

001 /* Listing2804.java */

002

003 import java.awt.*;

004 import java.awt.event.*;

import javax.swing.*

005

006 public class Listing2804

007 extends JFrame

008 {

009 public static void main(String[] args)

010 {

011 Listing2804 wnd = new Listing2804();

012 }

013

014 public Listing2804()

015 {

016 super("Nachrichtentransfer");

017 etBackground(Color.lightGray);

018 setSize(300,200);

019 setLocation(200,100);

020 setVisible(true);

021 addKeyListener(

022 new KeyAdapter() {

023 public void keyPressed(KeyEvent event)

024 {

025 if (event.getKeyCode() == KeyEvent.VK_ESCAPE) {

026 setVisible(false);

027 dispose();

028 System.exit(0);

029 }

030 }

031 }

032 );

033 }

034

Page 59: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

59

035 public void paint(Graphics g)

036 {

037 g.setFont(new Font("Serif",Font.PLAIN,18));

038 g.drawString("Zum Beenden bitte ESC drücken...",10,50);

039 }

040 }

Listing 28.4: Verwendung einer anonymen Klasse als Ereignishandler

Vorteilhaft bei dieser Vorgehensweise ist der verminderte Aufwand, denn es muss keine separate Klassendefinition angelegt

werden. Statt dessen werden die wenigen Codezeilen, die zur Anpassung der Adapterklasse erforderlich sind, dort eingefügt,

wo die Klasse instanziert wird, nämlich beim Registrieren des Nachrichtenempfängers. Anonyme Klassen haben einen

ähnlichen Einsatzbereich wie lokale, empfehlen sich aber vor allem, wenn sehr wenig Code für den Ereignisempfänger

benötigt wird. Bei aufwendigeren Ereignisempfängern ist die explizite Definition einer benannten Klasse dagegen

vorzuziehen.

Variante 3: Trennung von GUI- und Anwendungscode Wir hatten am Anfang darauf hingewiesen, daß in größeren Programmen eine Trennung zwischen Programmcode, der für die

Oberfläche zuständig ist, und solchem, der für die Anwendungslogik zuständig ist, wünschenswert wäre. Dadurch wird eine

bessere Modularisierung des Programms erreicht, und der Austausch oder die Erweiterung von Teilen des Programms wird

erleichtert.

Das Delegation Event Model wurde auch mit dem Designziel entworfen, eine solche Trennung zu ermöglichen

bzw. zu erleichtern. Der Grundgedanke dabei war es, auch Nicht-Komponenten die Reaktion auf GUI-Events zu

ermöglichen. Dies wurde dadurch erreicht, daß jede Art von Objekt als Ereignisempfänger registriert werden kann,

solange es die erforderlichen Listener-Interfaces implementiert. Damit ist es möglich, die Anwendungslogik

vollkommen von der grafischen Oberfläche abzulösen und in Klassen zu verlagern, die eigens für diesen Zweck

entworfen wurden.

Hinweis

Das nachfolgende Beispiel zeigt diese Vorgehensweise, indem es unser Beispielprogramm in die drei Klassen

Listing2805, MainFrameCommand und MainFrameGUI aufteilt. Listing2805 enthält nur noch die main-

Methode und dient lediglich dazu, die anderen beiden Klassen zu instanzieren. MainFrameGUI realisiert die GUI-

Funktionalität und stellt das Fenster auf dem Bildschirm dar. MainFrameCommand spielt die Rolle des

Kommandointerpreters, der immer dann aufgerufen wird, wenn im Fenster ein Tastaturereignis aufgetreten ist.

Die Verbindung zwischen beiden Klassen erfolgt durch Aufruf der Methode addKeyListener in MainFrameGUI, an die

das an den Konstruktor übergebene MainFrameCommand-Objekt weitergereicht wird. Dazu ist es erforderlich, daß das

Hauptprogramm den Ereignisempfänger cmd zuerst instanziert, um ihn bei der Instanzierung des GUI-Objekts gui übergeben

zu können.

Umgekehrt benötigt natürlich auch das Kommando-Objekt Kenntnis über das GUI-Objekt, denn es soll ja das

zugeordnete Fenster schließen und das Programm beenden. Der scheinbare Instanzierungskonflikt durch diese zirkuläre

Beziehung ist aber in Wirklichkeit gar keiner, denn bei jedem Aufruf einer der Methoden von MainFrameCommand

wird an das KeyEvent-Objekt der Auslöser der Nachricht übergeben, und das ist in diesem Fall stets das

MainFrameGUI-Objekt gui. So kann innerhalb des Kommando-Objekts auf alle öffentlichen Methoden des GUIObjekts

zugegriffen werden.

Tip 001 /* Listing2805.java */

002

003 import java.awt.*;

004 import java.awt.event.*;

005 import javax.swing.*

006 public class Listing2805

007 {

008 public static void main(String[] args)

009 {

010 MainFrameCommand cmd = new MainFrameCommand();

011 MainFrameGUI gui = new MainFrameGUI(cmd);

012 }

013 }

014

Page 60: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

60

015 class MainFrameGUI

016 extends JFrame

017 {

018 public MainFrameGUI(KeyListener cmd)

019 {

020 super("Nachrichtentransfer");

021 setBackground(Color.lightGray);

022 setSize(300,200);

023 setLocation(200,100);

024 setVisible(true);

025 addKeyListener(cmd);

026 }

027

028 public void paint(Graphics g)

029 {

030 g.setFont(new Font("Serif",Font.PLAIN,18));

031 g.drawString("Zum Beenden bitte ESC drücken...",10,50);

032 }

033 }

034

035 class MainFrameCommand

036 implements KeyListener

037 {

038 public void keyPressed(KeyEvent event)

039 {

040 JFrame source = (JFrame)event.getSource();

041 if (event.getKeyCode() == KeyEvent.VK_ESCAPE) {

042 source.setVisible(false);

043 source.dispose();

044 System.exit(0);

045 }

046 }

047

048 public void keyReleased(KeyEvent event)

049 {

050 }

051

052 public void keyTyped(KeyEvent event)

053 {

054 }

055 }

Listing 28.5: Trennung von GUI- und Anwendungslogik

Diese Designvariante ist vorwiegend für größere Programme geeignet, bei denen eine Trennung von Programmlogik und

Oberfläche sinnvoll ist. Für sehr kleine Programme oder solche, die wenig Ereigniscode haben, sollte eher eine der vorherigen

Varianten angewendet werden, wenn diese zu aufwendig ist. Sie entspricht in groben Zügen dem Mediator-Pattern, das in

"Design-Patterns" von Gamma et al. beschrieben wird.

Natürlich erhebt das vorliegende Beispielprogramm nicht den Anspruch, unverändert in ein sehr großes Programm

übernommen zu werden. Es soll lediglich die Möglichkeit der Trennung von Programmlogik und Oberfläche in einem großen

Programm mit Hilfe der durch das Event-Handling des JDK 1.1 vorgegebenen Möglichkeiten aufzeigen. Eine sinnvolle

Erweiterung dieses Konzepts könnte darin bestehen, weitere Modularisierungen vorzunehmen (z.B. analog dem MVC-Konzept

von Smalltalk, bei dem GUI-Anwendungen in Model-, View- und Controller-Layer aufgesplittet werden, oder auch durch

Abtrennen spezialisierter Kommandoklassen). Empfehlenswert ist in diesem Zusammenhang die Lektüre der

JDKDokumentation, die ein ähnliches Beispiel in leicht veränderter Form enthält.

Page 61: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

61

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 576 – 00 – TH – 02

-----------------------------------------------------------------------------------

Ereignisverarbeitung in JFC-GUI-Komponenten (6)

Demonstrationsprogramm zum Interface ActionListener

// ColorChangeDemo.java

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class ColorChangeDemo extends JFrame

{

Container c;

JButton but;

public ColorChangeDemo()

{

super("ColorChangeDemo");

c=getContentPane();

c.setLayout(new FlowLayout());

but = new JButton("Change Backgroundcolor");

c.add(but);

// ActionListener-Klasse als anonyme Klasse

ActionListener actlis = new ActionListener()

{

public void actionPerformed(ActionEvent e)

{

float rwert = (float)Math.random();

float gwert = (float)Math.random();

float bwert = (float)Math.random();

c.setBackground(new Color(rwert, gwert, bwert));

}

};

but.addActionListener(actlis);

setSize(300, 200);

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

public static void main(String[] args)

{

new ColorChangeDemo().setVisible(true);

}

}

Page 62: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

62

FACHHOCHSCHULE MUENCHEN FACHBEREICH ELEKTROTECHNIK UND INFORMATIONSTECHNIK

BEREICH DATENTECHNIK V – JV – 577 – 00 – TH – 01

-----------------------------------------------------------------------------------

Ereignisverarbeitung in JFC-GUI-Komponenten (6)

Demonstrationsprogramm zur Adapter-Klasse WindowAdapter

// WindowClosingDemo.java

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class WindowClosingDemo extends JFrame

{ Container c;

JLabel lab;

JCheckBox cb1, cb2;

public WindowClosingDemo()

{ super("Window Closing Demo");

c = getContentPane();

c.setLayout(new FlowLayout());

lab = new JLabel("Zum Schliessen des Fensters bitte " +

"beide Auswahlfelder selektieren");

lab.setBorder(BorderFactory.createEmptyBorder(10, 0, 25, 0));

cb1 = new JCheckBox("Auswahl 1");

cb2 = new JCheckBox("Auswahl 2");

c.add(lab);

c.add(cb1);

c.add(cb2);

addWindowListener(new ClosingListener());

setSize(400, 150);

setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

}

// WindowListener-Klasse als innere Klasse

public class ClosingListener extends WindowAdapter

{

public void windowClosing(WindowEvent e)

{ if (cb1.isSelected() && cb2.isSelected())

{ e.getWindow().dispose();

System.exit(0);

}

else

JOptionPane.showMessageDialog(c, "Vor dem Schliessen " +

"beide Auswahlfelder selektieren");

}

}

public static void main(String[] args)

{ new WindowClosingDemo().setVisible(true);

}

}

Page 63: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

63

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 56C – 03 – TH – 01

------------------------------------------------------------------------------------

Komplexe Swing-Komponenten-Klassen (1)

JList Die Klasse JList dient dazu, Listen von Werten darzustellen, aus denen der Anwender einen oder mehrere Einträge

auswählen kann. Im Gegensatz zur AWT-Klasse List kann sie nicht nur Strings, sondern beliebige Objekte enthalten. Auch

die Darstellung der Listenelemente auf dem Bildschirm kann weitgehend frei gestaltet werden. Wir wollen uns die wichtigsten

Eigenschaften von JList ansehen und dazu zunächst mit den Konstruktoren beginnen:

public JList()

public JList(Object[] listData)

public JList(Vector listData)

public JList(ListModel dataModel)

Der parameterlose Konstruktor erzeugt eine leere Liste. Wird ein Array oder Vector übergeben, erzeugt JList aus dessen

Daten ein Listenmodell und benutzt es zur Darstellung. Schließlich kann auch direkt eine Instanz der Klasse ListModel

übergeben werden, um den Inhalt der Liste zu definieren.

Ähnlich wie JTextArea und andere Swing-Komponenten besitzt JList keine eigene Funktionalität zum

Scrollen der Daten, falls diese nicht vollständig auf den Bildschirm passen. Eine JList wird daher meist in eine

JScrollPane eingebettet, bevor sie zu einem GUI-Container hinzugefügt wird.

Hinweis

Selektieren von Elementen

Die meisten Methoden der Klasse JList haben mit der Selektion der Listenelemente zu tun. Eine Liste kann sowohl Einzel als

auch Mehrfachselektion unterstützen: public int getSelectionMode()

public void setSelectionMode(int selectionMode)

Mit setSelectionMode wird der Selektionsmodus verändert. Als Argument kann eine der folgenden Konstanten der

Klasse ListSelectionModel übergeben werden:

l SINGLE_SELECTION: Es kann maximal ein Element ausgewählt werden

l SINGLE_INTERVAL_SELECTION: Es können mehrere Elemente eines zusammenhängenden Bereichs

ausgewählt werden

l MULTIPLE_INTERVAL_SELECTION: Eine beliebige Auswahl von Elementen kann selektiert werden

getSelectionMode liefert den aktuellen Selektionsmodus. Es gibt eine Reihe von Methoden, um Informationen über die

derzeit selektierten Elemente zu beschaffen: public int getSelectedIndex()

public int[] getSelectedIndices()

public Object getSelectedValue()

public Object[] getSelectedValues()

public boolean isSelectedIndex(int index)

public boolean isSelectionEmpty()

public int getAnchorSelectionIndex()

public int getLeadSelectionIndex()

getSelectedIndex liefert den Index des selektierten Elements, falls der Selektionsmodus SINGLE_SELECTION ist.

Können mehrere Elemente ausgewählt werden, liefert getSelectedIndices ein Array mit den Indizes aller selektierten

Elemente. getSelectedValue und getSelectedValues arbeiten in analoger Weise, liefern aber statt der Indizes die

selektierten Elemente zurück. Mit isSelectedIndex kann geprüft werden, ob das Element mit dem angegebenen Index

gerade selektiert ist, und isSelectionEmpty prüft, ob mindestens ein Element selektiert wurde.

Als "Anchor" und "Lead" bezeichnet Swing in einem zusammenhängend markierten Bereich das jeweils zuerst und zuletzt

markierte Element. Das zuletzt markierte Element ist gleichzeitig aktuelles Element. Mit getAnchorSelectionIndex

und getLeadSelectionIndex kann auf "Anchor" und "Lead" zugegriffen werden, wenn der Selektionsmodus

SINGLE_INTERVAL_SELECTION ist.

Zusätzlich gibt es Methoden, um die Selektion programmgesteuert zu verändern: public void clearSelection()

public void setSelectedIndex(int index)

public void setSelectedIndices(int[] indices)

public void setSelectionInterval(int anchor, int lead)

public void addSelectionInterval(int anchor, int lead)

public void removeSelectionInterval(int index0, int index1)

Page 64: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

64

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 56C – 03 – TH – 01

------------------------------------------------------------------------------------

Komplexe Swing-Komponenten-Klassen (2)

Mit clearSelection wird die Selektion gelöscht. Mit setSelectedIndex kann ein einzelnes Element selektiert

werden, mit setSelectedIndices eine Menge von Elementen. Mit setSelectionInterval,

addSelectionInterval und removeSelectionInterval können Selektionen auch bereichsweise hinzugefügt und

gelöscht werden.

Wird die Selektion geändert, versendet eine JList ein ListSelectionEvent an alle registrierten Listener. Um im

Programm auf Änderungen zu reagieren, ist also lediglich das Interface ListSelectionListener des Pakets

javax.swing.event zu implementieren und durch Aufruf von addListSelectionListener bei der JList zu

registrieren. Jede Selektionsänderung führt dann zum Aufruf der Methode valueChanged.

Den Listeninhalt dynamisch verändern

Etwas mehr Aufwand als beim AWT-Pendant muß getrieben werden, wenn der Inhalt einer JList nach der Instanzierung

modifiziert werden soll. In diesem Fall kann nicht mehr mit dem automatisch erzeugten Listenmodel gearbeitet werden,

sondern es muß selbst eines erzeugt werden. Das Modell einer JList muß stets das Interface ListModel implementieren

und der Liste durch Versenden eines ListDataEvent jede Datenänderung mitteilen. Eine für viele Zwecke ausreichende

Implementierung steht mit der Klasse DefaultListModel zur Verfügung. Ihre Schnittstelle entspricht der Klasse Vector

und alle erforderlichen Änderungsbenachrichtigungen werden automatisch verschickt. Die wichtigsten

Methoden von DefaultListModel sind:

public void clear()

public void addElement(Object obj)

public void removeElementAt(int index)

public int size()

public Object elementAt(int index)

Soll eine Liste mit einem benutzerdefinierten Modell arbeiten, wird dieses einfach manuell erzeugt und an den Konstruktor

übergeben. Alle Einfügungen, Löschungen und Änderungen von Daten werden dann an diesem Modell vorgenommen. Durch

Aufruf von getModel kann auf einfache Weise auf das Modell einer JList zugegriffen werden.

Beispiel

Zum Abschluss wollen wir uns ein Beispiel ansehen. Das folgende Programm instanziert eine JList durch Übergabe eines

String-Arrays. Bei jedem Drücken des Buttons "Ausgabe" gibt es die Liste der selektierten Elemente auf der Konsole aus: 001 /* Listing3710.java */

002

003 import java.awt.*;

004 import java.awt.event.*;

005 import javax.swing.*;

006

007 public class Listing3710

008 extends JFrame

009 implements ActionListener

010 {

011 static final String[] DATA = {

012 "Hund", "Katze", "Meerschweinchen", "Tiger", "Maus",

013 "Fisch", "Leopard", "Schimpanse", "Kuh", "Pferd",

014 "Reh", "Huhn", "Marder", "Adler", "Nilpferd"

015 };

016

017 private JList list;

018

019 public Listing3710()

020 {

021 super("JList");

022

023 Container cp = getContentPane();

024 //Liste

025 list = new JList(DATA);

026 list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);

029 list.setSelectedIndex(2);

Page 65: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

65

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK V – JV – 56C – 03 – TH – 01

------------------------------------------------------------------------------------

Komplexe Swing-Komponenten-Klassen (3)

030 cp.add(new JScrollPane(list), BorderLayout.CENTER);

031 //Ausgabe-Button

032 JButton button = new JButton("Ausgabe");

033 button.addActionListener(this);

034 cp.add(button, BorderLayout.SOUTH);

035 }

036

037 public void actionPerformed(ActionEvent event)

038 {

039 String cmd = event.getActionCommand();

040 if (cmd.equals("Ausgabe")) {

041 System.out.println("---");

042 ListModel lm = list.getModel();

043 int[] sel = list.getSelectedIndices();

044 for (int i = 0; i < sel.length; ++i) {

045 String value = (String)lm.getElementAt(sel[i]);

046 System.out.println(" " + value);

047 }

048 }

049 }

050

051 public static void main(String[] args)

052 {

053 Listing3710 frame = new Listing3710();

054 frame.setLocation(100, 100);

055 frame.setSize(200, 200);

056 frame.setVisible(true);

057 }

058 }

Listing 37.10: Die Klasse JList

Die Programmausgabe ist:

Page 66: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

66

Listing3710 mit DefaultListModel //Das interne ListModel verfügt nur über die Methoden getSize u. getElementAt

//Falls man z. auch Einfügen und Löschen will, muss das DefaultListModel oder

//ein eigenes ListModel verwendet werden

package list;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class Listing3710

extends JFrame

implements ActionListener

{

//Membervariable

static final String[] DATA = {

"Hund", "Katze", "Meerschweinchen", "Tiger", "Maus",

"Fisch", "Leopard", "Schimpanse", "Kuh", "Pferd",

"Reh", "Huhn", "Marder", "Adler", "Nilpferd"

};

private JList list=null;

//Default-ListModel, Schnittstelle entspricht der Klasse Vector

private DefaultListModel lm= new DefaultListModel();

private JTextField jTextField1 = new JTextField();

public Listing3710()

{

super("JList-Demo DefaultListModel");

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

Container cp = getContentPane();

cp.setLayout(new BorderLayout());

//Liste

list = new JList(lm/*DATA*/);

list.setModel(lm);

for(int i=0;i<DATA.length;i++)

{

lm.addElement(DATA[i]);

}

list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

list.setSelectedIndex(2);

cp.add(new JScrollPane(list), BorderLayout.CENTER);

//Ausgabe-Button

JButton button = new JButton("Ausgabe+Delete");

button.addActionListener(this);

cp.add(button, BorderLayout.SOUTH);

}

public void actionPerformed(ActionEvent event)

{

String cmd = event.getActionCommand();

if (cmd.equals("Ausgabe+Delete")) {

System.out.println("---");

//ListModel lm = list.getModel();

int[] sel = list.getSelectedIndices();

for (int i = 0; i < sel.length; ++i) {

String value = (String)lm.getElementAt(sel[i]);

System.out.println(" " + value);

Page 67: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

67

lm.removeElementAt(sel[i]); //nur bei DefaultListModel

}

}

}

public static void main(String[] args)

{

Listing3710 frame = new Listing3710();

frame.setLocation(100, 100);

frame.setSize(200, 200);

frame.setVisible(true);

}

}

Page 68: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

68

FACHHOCHSCHULE MUENCHEN FAKULTÄT FÜR ELEKTROTECHNIK UND INFORMATIONSTECHNIK

FG TECHNISCHE INFORMATIK

------------------------------------------------------------------------------------

Entwurfsmuster (design-pattern) mit GUI-Bezug

Design-Patterns (oder Entwurfsmuster) sind eine der wichtigsten und interessantesten Entwicklungen der objektorientierten

Programmierung der letzten Jahre. Basierend auf den Ideen des Architekten Christopher Alexander wurden sie durch das Buch

"Design-Patterns - Elements of Reusable Object-Oriented Software" von Erich Gamma, Richard Helm, Ralph Johnson und

John Vlissides 1995 einer breiten Öffentlichkeit bekannt.

Als Design-Patterns bezeichnet man (wohlüberlegte) Designvorschläge für den Entwurf objektorientierter Softwaresysteme.

Ein Design-Pattern deckt dabei ein ganz bestimmtes Entwurfsproblem ab und beschreibt in rezeptartiger Weise das

Zusammenwirken von Klassen, Objekten und Methoden. Meist sind daran mehrere Algorithmen und/oder Datenstrukturen

beteiligt. Design-Patterns stellen wie Datenstrukturen oder Algorithmen vordefinierte Lösungen für konkrete

Programmierprobleme dar, allerdings auf einer höheren Abstraktionsebene.

Einer der wichtigsten Verdienste standardisierter Design-Patterns ist es, Softwaredesigns Namen zu geben. Zwar ist es in der

Praxis nicht immer möglich oder sinnvoll, ein bestimmtes Design-Pattern in allen Details zu übernehmen. Die konsistente

Verwendung ihrer Namen und ihres prinzipiellen Aufbaus erweitern jedoch das Handwerkszeug und die

Kommunikationsfähigkeit des OOP-Programmierers beträchtlich. Begriffe wie Factory, Iterator oder Singleton werden in OOP

-Projekten routinemäßig verwendet und sollten für jeden betroffenen Entwickler dieselbe Bedeutung haben.

Wir wollen nachfolgend einige der wichtigsten Design-Patterns vorstellen und ihre Implementierung in Java skizzieren. Die

Ausführungen sollten allerdings nur als erster Einstieg in das Thema angesehen werden. Viele Patterns können hier aus

Platzgründen gar nicht erwähnt werden, obwohl sie in der Praxis einen hohen Stellenwert haben (z.B. Adapter, Bridge,

Mediator, Command etc.). Zudem ist die Bedeutung eines Patterns für den OOP-Anfänger oft gar nicht verständlich, sondern

erschließt sich erst nach Monaten oder Jahren zusätzlicher Programmiererfahrung.

Die folgenden Abschnitte ersetzen also nicht die Lektüre weiterführender Literatur zu diesem Thema. Das oben erwähnte Werk

von Gamma et al. ist nach wie vor einer der Klassiker schlechthin (die Autoren und ihr Buch werden meist als "GoF"

bezeichnet, ein Akronym für "Gang of Four"). Daneben existieren auch spezifische Kataloge, in denen die Design-Patterns zu

bestimmten Anwendungsgebieten oder auf der Basis einer ganz bestimmten Sprache, wie etwa C++ oder Java, beschrieben

werden.

Page 69: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

69

Composite-Muster In der Programmierpraxis werden häufig Datenstrukturen benötigt, bei denen die einzelnen Objekte zu Baumstrukturen

zusammengesetzt werden können.

Es gibt viele Beispiele für derartige Strukturen:

l Die Menüs in einem Programm enthalten Menüpunkte und Untermenüs. Untermenüs enthalten weitere Menüpunkte,

sind aber selbst Menüpunkte im übergeordneten Menü.

l Ein Verzeichnis in einem Dateisystem enthält Dateien und Unterverzeichnisse. Unterverzeichnisse weisen dieselbe

prinzipielle Struktur wie ihre übergeordneten Verzeichnisse auf. Sowohl Dateien als auch Unterverzeichnisse haben

gemeinsame Eigenschaften, wie etwa einen Namen oder zugeordnete Rechte.

l Die Komponenten einer grafischen Oberfläche können sowohl einfache Dialogelemente (Buttons, Textfelder,

Listboxen) als auch Container (Unterfenster, Split-Panels, Tab-Panels) sein. Container enthalten ebenfalls

Komponenten (vergleiche zum Beispiel die Hierarchie der AWT-Fensterklassen).

l Ein mechanisches Bauteil besteht aus elementaren Teilen, die nicht mehr weiter zerlegt werden können, und

zusammengesetzten Bauteilen, die aus Unterbauteilen bestehen.

Für diese häufig anzutreffende Abstraktion gibt es ein Design-Pattern, das als Composite bezeichnet wird. Es ermöglicht

derartige Kompositionen und erlaubt eine einheitliche Handhabung von individuellen und zusammengesetzten Objekten. Ein

Composite enthält folgende Bestandteile:

l Eine (oft abstrakte) Basisklasse, die sowohl zusammengesetzte als auch elementare Objekte repräsentiert. Diese

Basisklasse wird auch als "Component" bezeichnet.

l Alle elementaren Objekte sind aus dieser Basisklasse abgeleitet.

l Daraus abgeleitet gibt es mindestens eine Containerklasse, die in der Lage ist, eine Menge von Objekten der

Basisklasse aufzunehmen.

Somit sind beide Bedingungen erfüllt. Der Container ermöglicht die Komposition der Objekte zu Baumstrukturen, und die

Basisklasse stellt die einheitliche Schnittstelle für elementare Objekte und Container zur Verfügung.

Das Klassendiagramm für ein Composite sieht so aus:

Klassendiagramm eines Composite

Das folgende Listing skizziert dieses Design-Pattern am Beispiel einer einfachen Menüstruktur:

001 /* Listing1013.java */

002

003 class MenuEntry1

004 {

005 protected String name;

006

007 public MenuEntry1(String name)

008 {

009 this.name = name;

010 }

011

012 public String toString()

013 {

014 return name;

015 }

016 }

017

AbstractComponent

ConcreteComponent 1

ConcreteComponent 2

Container

Page 70: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

70

018 class IconizedMenuEntry1 extends MenuEntry1

020 {

021 private String iconName;

022

023 public IconizedMenuEntry1(String name, String iconName){

025 super(name);

026 this.iconName = iconName;

027 }

028 }

029

030 class CheckableMenuEntry1 extends MenuEntry1

032 {

033 private boolean checked;

034

035 public CheckableMenuEntry1(String name, boolean checked) {

037 super(name);

038 this.checked = checked;

039 }

040 }

041

042 class Menu1 extends MenuEntry1

044 {

045 MenuEntry1[] entries;

046 int entryCnt;

047

048 public Menu1(String name, int maxElements) {

050 super(name);

051 this.entries = new MenuEntry1[maxElements];

052 entryCnt = 0;

053 }

054

055 public void add(MenuEntry1 entry) {

057 entries[entryCnt++] = entry;

058 }

059

060 public String toString()

061 {

062 String ret = "(";

063 for (int i = 0; i < entryCnt; ++i) {

064 ret += (i != 0 ? ",": "") + entries[i].toString();

065 }

066 return ret + ")";

067 }

068 }

069

070 public class Listing1013

071 {

072 public static void main(String[] args)

073 {

074 Menu1 filemenu = new Menu1("Datei", 5);

075 filemenu.add(new MenuEntry1("Neu"));

076 filemenu.add(new MenuEntry1("Laden"));

077 filemenu.add(new MenuEntry1("Speichern"));

078

079 Menu1 confmenu = new Menu1("Konfiguration", 3);

080 confmenu.add(new MenuEntry1("Farben"));

081 confmenu.add(new MenuEntry1("Fenster"));

082 confmenu.add(new MenuEntry1("Pfade"));

083 filemenu.add(confmenu);

084

085 filemenu.add(new MenuEntry1("Beenden"));

086

087 System.out.println(filemenu.toString());

088 }

089 }

Listing 10.13: Das Composite-Pattern

Page 71: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

71

Die Komponentenklasse hat den Namen MenuEntry1. Sie repräsentiert Menüeinträge und ist Vaterklasse der

spezialisierten Menüeinträge IconizedMenuEntry1 und CheckableMenuEntry1. Zudem ist sie Vaterklasse des

Containers Menu1, der Menüeinträge aufnehmen kann.

Bestandteil der gemeinsamen Schnittstelle ist die Methode toString. In der Basisklasse und den elementaren Menüeinträgen

liefert sie lediglich den Namen des Objekts. In der Containerklasse wird sie überlagert und liefert eine geklammerte Liste aller

darin enthaltener Menüeinträge. Dabei arbeitet sie unabhängig davon, ob es sich bei dem jeweiligen Eintrag um einen

elementaren oder einen zusammengesetzten Eintrag handelt, denn es wird lediglich die immer verfügbare Methode toString

aufgerufen.

Das Testprogramm erzeugt ein "Datei"-Menü mit einigen Elementareinträgen und einem Untermenü "Konfiguration" und gibt

es auf Standardausgabe aus: (Neu,Laden,Speichern,(Farben,Fenster,Pfade),Beenden)

Page 72: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

72

Observer-Muster Bei der objektorientierten Programmierung werden Programme in viele kleine Bestandteile zerlegt, die für sich genommen

autonom arbeiten. Mit zunehmender Anzahl von Bausteinen steigt allerdings der Kommunikationsbedarf zwischen diesen

Objekten, und der Aufwand, sie konsistent zu halten, wächst an. Ein Observer ist ein Design-Pattern, das eine Beziehung

zwischen einem Subject und seinen Beobachtern aufbaut. Als Subjectwird dabei ein Objekt bezeichnet, dessen Zustands-

änderung für andere Objekte interessant ist. Als Beobachter werden die Objekte bezeichnet, die von Zustandsänderungen des

Subjekts abhängig sind; deren Zustand also dem Zustand des Subjekts konsistent folgen muß.

Kurzbeschreibung Ermöglicht die dynamische Registrierung von Objektabhängigkeiten, so dass bei einem Zustandswechsel eines

Objekts alle von ihm abhängigen Objekte benachrichtigt werden.

Problembeschreibung

In vielen Anwendungsbereichen soll sich der Zustandswechsel eines Objekts direkt auf den Zustand bzw. das Verhalten

anderer Objekte auswirken.

Beispiel : Ein Datenbestand und seine – u.U. gleichzeitige – Darstellung in verschiedenen Formaten in einem GUI-System

(z. B. Tabelle, Balkendiagramm, Tortendiagramm). Jede Änderung des Datenbestandes muss sich umgehend auf alle Dar-

stellungen auswirken.

Eine enge Kopplung der beteiligten Objekte ( die beteiligten Objekte haben voneinander Kenntnis) ist meist nicht

wünschenswert, da dadurch die unabhängige Verwendung und Modifikation ihrer jeweiligen Klassen stark eingeschränkt

wird. Außerdem müssen in diesem Fall die Abhängigkeiten bereits zur Compilezeit bekannt sein, was eine flexible

dynamische Anpassung zur Laufzeit verhindert.

Problemlösung Bei dem Objekt, von dessen Zustand andere Objekte abhängen (Publisher-Objekt), wird eine Liste der abhängigen

Objekte geführt. In diese Liste tragen sich alle Objekte, die über den Zustand dieses Objekts auf dem Laufenden gehalten

werden wollen (weil sie von ihm abhängen), ein (Subscriber-Objekte, Observer-Objekte).

Bei einem Wechsel seines Zustands informiert das Publisher-Objekt alle eingetragenen Observer-Objekt hierüber (notify).

Diese können dann den neuen Zustand vom Publisher-Objekt ermitteln und entsprechend der eingetretenen Änderung

reagieren (z.B. ihren eigenen Zustand an den Zustand des Publisher-Objektes anpassen).

Die Anzahl der Observer-Objekte muss dem Publisher-Objekt a priori nicht bekannt sein. Bei ihm können sich zur

Laufzeit beliebig viele Observer-Objekte an- bzw. auch wieder abmelden.

Publisher-Objekt und Observer-Objekte sind von einander entkoppelt und können unabhängig voneinander modifiziert

werden.

Die Publisher-Schnittstelle wird durch eine geeignete Klasse (Publisher) zur Verfügung gestellt. Diese Klasse dient als

Basisklasse für konkrete Publisher-Klassen (ConcretePublisher), die die Datenkomponenten für den jeweiligen

Zustand und die Methoden zum Setzen und Ermitteln derselben bereitstellen.

Das Interface zum Informieren von Observer-Objekten wird durch eine abstrakte Klasse (Observer) definiert

Dieses Interface wird von konkreten Observer-Klassen (ConcreteObserver) implementiert. Objekte dieser Klassen

enthalten – neben ihren eigentlichen Zustands-Datenkomponenten – eine Referenz auf das konkrete Publisher-Objekt, bei

dem sie sich eingetragen haben.

Abbildung 10.8: Klassendiagramm eines Observers

Publisher

-observers:Observer

+attach:Observer +detach:Observer +notify:void

publisher

1

0..n observers

interface Observer

+update:void

ConcreteObserver

-observState:State -publisher:ConcretePublisher

+update:void

ConcretePublisher

-subjState:State

+setState:void +getState:State

void notify()

{ for all o

in observers

o.update();

}

Page 73: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

73

Anwendungskonsequenzen

▻ Publisher und Observer können unabhängig voneinander geändert und ausgetauscht werden.

Publisher können wiederbenutzt werden, ohne ihre Observer wiederzubenutzen und umgekehrt.

Observer können hinzugefügt werden, ohne den Publisher oder andere Observer zu verändern.

▻ Die Kopplung zwischen Publisher und Observer ist abstrakt und minimal.

Ein Publisher-Objekt weiß lediglich, dass es eine Liste von Observer-Objekten besitzt, die das Observer-Interface

implementieren. Es kennt nicht die konkrete Klasse seiner Observer.

Publisher und Observer können unterschiedlichen Abstraktions-Ebenen (Schichtenmodell !) angehören.

▻ Observer-Objekte können gegebenenfalls selbst auch einen Zustandswechsel beim Publisher-Objekt bewirken

▻ Die Information über den Zustandswechsel (Notifikation) durch das Publisher-Objekt ist automatisch eine Broadcast-

Kommunikation. Es werden immer alle eingetragenen Observer-Objekte informiert, unabhängig davon, wieviel es sind.

Es obliegt einem Observer-Objekt, eine Notifikation gegebenenfalls zu ignorieren.

▻ Falls sehr viele Observer-Objekte eingetragen sind, kann eine Notifikation und der dadurch ausgelöste Observer-Update

u.U. eine längere Zeit dauern.

▻ Da das eine Zustandsänderung bewirkende Objekt keine Information über die Observer und die mit diesen verbundenen

"Update"-Kosten hat, können "leichtfertige" Zustandsänderungen einen erheblichen zeit- und damit kostenintensiven

Aufwand bewirken.

▻ Das einfache Notifikations-Protokoll liefert keine Informationen darüber, was sich im Publisher-Objekt geändert

hat. Dies festzustellen, obliegt dem Observer-Objekt, was den Update-Aufwand gegebenenfalls noch erhöht.

Als Alternative kann u.U. ein erweitertes Protokoll definiert werden, dass detailliertere Zustandsänderungs-Info liefert.

▻ Es gibt Fälle, bei denen sinnvoll ist, dass sich ein Observer-Objekt bei mehreren Publisher-Objekten für eine

Notifikation einträgt. In diesen Fällen muss die Update-Botschaft eine Information über das absendende Publisher-

Objekt enthalten

Page 74: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

74

Das folgende Listing zeigt eine beispielhafte Implementierung: 001 /* Listing1015.java */

002 package observer;

003 interface Observer

004 {

005 public void update(Subject subject);

006 }

007

008 class Subject //Publisher

009 {

010 Observer[] observers = new Observer[5];

011 int observerCnt = 0;

012

013 public void attach(Observer observer)

014 {

015 observers[observerCnt++] = observer;

016 }

017

018 public void detach(Observer observer)

019 {

020 for (int i = 0; i < observerCnt; ++i) {

021 if (observers[i] == observer) {

022 --observerCnt;

023 for (;i < observerCnt; ++i) {

024 observers[i] = observers[i + 1];

025 }

026 break;

027 }

028 }

029 }

030

031 public void fireUpdate()

032 {

033 for (int i = 0; i < observerCnt; ++i) {

034 observers[i].update(this);

035 }

036 }

037 }

//Concrete Publisher (Subject)

class Counter extends Subject{

int cnt = 0;

public void inc() {

++cnt;

fireUpdate();

}

}

//class Listing1015 ist Applikationsklasse und konkreter Observer durch Implementierung des Interfaces

//Observer als anonyme Klasse public class Listing1015

{

public static void main(String[] args)

{

Counter counter = new Counter();

counter.attach( new Observer() {

public void update(Subject subject){

System.out.println("divisible by 3: ");

}

});

while (counter.cnt < 10) {

counter.inc();

System.out.println(counter.cnt);

}

}

}

Listing: Das Observer-Pattern

Page 75: Programmieren in Java - hmtasin/vorlesung_oop/oop_Teil2_java_gui.pdfProgrammieren in Java Kapitel 5 5. Graphische Benutzeroberflächen 5.1 Grundprinzip 5.2 Java Foundation Classes

75

Als konkreter Publisher wird hier die Klasse Counter verwendet. Sie erhöht bei jedem Aufruf von inc den eingebauten

Zähler um eins und informiert alle registrierten Beobachter, falls der neue Zählerstand durch drei teilbar ist. Im Hauptprogramm

instanzieren wir ein Counter-Objekt und registrieren eine lokale anonyme Klasse als Listener, die bei jeder Benachrichtigung

eine Meldung ausgibt. Während des anschließenden Zählerlaufs von 1 bis 10 wird sie dreimal aufgerufen: 1

2

divisible by 3: 3

4

5

divisible by 3: 6

7

8

divisible by 3: 9

10

Das Observer-Pattern ist in Java sehr verbreitet, denn die Kommunikation zwischen graphischen Dialogelementen

und ihrer Anwendung basiert vollständig auf dieser Idee. Allerdings wurde es etwas erweitert, die Beobachter

werden als Listener bezeichnet, und es gibt von ihnen eine Vielzahl unterschiedlicher Typen mit unterschiedlichen

Aufgaben. Da es zudem üblich ist, daß ein Listener sich bei mehr als einem Subjekt registriert, wird ein Aufruf von

update statt des einfachen Arguments jeweils ein Listener-spezifisches Ereignisobjekt übergeben. Darin werden

neben dem Subjekt weitere spezifische Informationen untergebracht. Zudem haben die Methoden gegenüber der

ursprünglichen Definition eine andere Namensstruktur, und es kann sein, daß ein Listener nicht nur eine, sonderen

mehrere unterschiedliche Update-Methoden zur Verfügung stellen muß, um auf unterschiedliche Ereignistypen zu

reagieren. Das Listener-Konzept von Java wird auch als Delegation Based Event Handling bezeichnet.

Hinweis