Java

Werbung
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
1
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 strukturierten 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 enthaltenen Komponenten können "elementare" Komponenten oder wiederum Container sein, welche dann weitere Komponenten 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.
2
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 Landessprache 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 WindowFunktionalitä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 vorgegebenen 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 PrimitivOperationen ("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ändern. 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.
3
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)
Component
Container
Label
JComponent
Window
AWT
Button
Frame
… weitere AWTKomponenten
Checkbox
ScrollPane
JWindow
JFrame
JDialog
JPanel
MenuItem
Panel
Menu
Dialog
Applet
PopupMenu
FileDialog
JApplet
JList
JScrollPane
JComboBox
Box
MenuComponent
Swing
CheckBoxMenuItem
JPopupMenu
JTable
JMenuBar
JToolBar
...
...
AbstractButton
MenuBar
Box.Filler
JLabel
JTextComponent
… weitere SwingKomponenten
...
JButton
...
JToggleButton
JRadioButton
JCheckBox
JMenuItem
JMenu
JTextArea
JCheckBoxMenuItem
JRadioButtonMenuItem
4
JTextField
JEditorPane
JPasswordField
JTextPane
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
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
 Elementare Komponenten (Auswahl)
JButton
JToggleButton
Umschaltknopf (Schaltknopf mit zwei Zuständen)
Auswahlfeld
Checkbox
JCheckBox
Gruppe alternativer Auswahlfelder
(nur ein Feld kann ausgewählt werden)
Checkbox
in Verbindung mit
CheckboxGroup
JRadioButton
in Verbindung mit
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
JTable
Tabelle
Menüeintrag
MenuItem
JMenuItem
AWT
Swing
Panel
JPanel
 "Innere" Container (Auswahl)
Gruppierungsfeld
Box
Gruppierungbox (festliegender Layout-Manager)
Menüleiste
MenuBar
JMenuBar
Menu
Menu
JMenu
JToolBar
Werkzeugleiste
5
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)
6
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-KomponentenKlassen.
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 GraphikContext-Objekts g.
Wird vom System aufgerufen (Callback), z.B. wenn die Komponente 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 )
7
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 Reihenfolge der Listenelemente standardmässig durch die Reihenfolge ihres Einfügens festgelegt ist.
Diese Reihenfolge bestimmt auch die Anordnungs-Reihenfolge der Komponenten entsprechend des jeweils festgelegten 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 )
public Component add(Component comp)
Einfügen der Komponente comp am Ende des Containers
public Component add(Component comp,
int idx)
Einfügen der Komponente comp an der Position idx
public Component add(Component comp,
Object constr)
Einfügen der Komponente comp unter Berücksichtigung
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
◇ 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
8
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 Komponente 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 Ermittlungs-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 undurchsichtig (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)
9
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 AWTAnwendungen) 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-LevelContainer-Klasse abgeleitet ist – von ausserhalb erfolgen.
10
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);
}
}
11
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);
}
}
12
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:
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,
int a)
Erzeugung eines Color-Objekts mit den angegebenen
RGB-Werten und dem angegebenen Alpha-Wert (a)
public Color(float r, float g, float b,
float a)
Erzeugung eines Color-Objekts mit den angegebenen
RGB-Werten und dem angegebenen Alpha-Wert (a)
 Memberfunktionen zur Ermittlung der Farb-Komponenten
◇ Neben zahlreichen anderen Memberfunktionen existieren die folgenden Methoden zum Ermitteln der einzelnen
Farbkomponenten eines Color-Objekts.
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
13
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 verwendenden 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 :
public Font(String name, int style, int size)
Erzeugung eines neuen Font-Objekts mit dem
Namen name, Stil style und Größe size
 Memberfunktionen zur Ermittlung der Font-Komponenten
◇
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
14
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 erfordert dann eine genaue Festlegung der Größe und der Position jeder einzelnen Komponente und führt zu Anpassungsproblemen, 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 Anordnungs-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.
15
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 Containergröß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 :
public BorderLayout()
Erzeugung eines BorderLayout-Objekts, das die Komponenten ohne Zwischenabstände anordnet
public BorderLayout(int hgap, int vgap)
Erzeugung eines BorderLayout-Objekts, das die Komponenten mit dem horizontalen Abstand hgap und dem
vertikalen Abstand vgap anordnet (Abstaende in Pixel)
◇ 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
16
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()
{ 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";
}
// BorderLayout ist Default bei JFrame
private void useFlowLayout()
{ //
}
private void useGridLayout()
{ //
}
private void useBoxLayout()
{ //
}
public static void main(String[] args)
{
new LayoutDemo().setVisisble(true);
}
}
17
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 :
public FlowLayout()
Erzeugung eines FlowLayout-Objekts, mit den Defaulteinstellungen (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,
int vgap)
Erzeugung eines FlowLayout-Objekts, mit einer durch
align festgelegten Ausrichtung und einem durch hgap
(horizontal) und vgap (vertikal) gegebenen Abstand
◇ 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 Komponenten zu den einzelnen Zeilen entsprechend angepasst.
◇ Beispiel : Flow-Layout eines JFrame-Containers mit fünf JButton-Komponenten
(Ergänzung / Modifikation des obigen Demonstrationsprogramms)
private void useFlowLayout()
{ c.setLayout(new FlowLayout());
for (int i=0; i<ba.length; i++)
c.add(ba[i]);
titel+="FlowLayout";
}
18
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 ausgenutzt 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 angegeben 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 :
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,
int hgap, int vgap)
Erzeugung eines GridLayout-Objekts, mit rows Zeilen
und cols Spalten (siehe oben), sowie einem durch hgap
(horizontal) und vgap (vertikal) gegebenen Zellen-Abstand
◇ Wird die Größe des Containers geändert (z.B. durch Ziehen mit der Maus), so wird – bei gleichbleibender Zeilenund 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)
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)";
}
19
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, maximale 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 Berücksichtigung der jeweiligen maximalen Breiten, die Breite aller Komponenten an die größte bevorzugte Breite anzupassen.
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 Containers) 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 :
public BoxLayout(Container con, int axis)
Erzeugung eines BoxLayout-Objekts für das
Container-Objekt con mit der durch axis
festgelegten Anordnungs-Achse
◇ Zur Festlegung der Anordnungs-Achse (Konstruktor-Parameter axis) stehen in der Klasse BoxLayout die folgenden 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 ursprü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)
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";
}
20
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).
21
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 Hintergrundfarbe 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)
22
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);
}
}
23
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)
Umrandung mit EmptyBorder
keine Umrandung
Umrandung mit EtchedBorder
Umrandung mit TitledBorder
Umrandung mit CompoundBorder aus Etchedborder und LineBorder
24
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-LevelContainer 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 ausserhalb 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)
public JFrame()
Erzeugung eines JFrame-Objekts ohne Titel, das durch das Objekt repräsentierte Fenster ist unsichtbar
public JFrame(String title)
Erzeugung eines JFrame-Objekts mit dem Titel title, das durch das
Objekt repräsentierte Fenster ist unsichtbar
◇ Memberfunktionen (Auswahl)
*) geerbt von Frame
**) geerbt von Window
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)
◇ 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(...)
25
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)
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,
String tit)
Erzeugung eines nicht-modalen JDialog-Objekts mit dem Titel tit und
dem Frame-(JFrame-)Objekt owner als "Besitzer"
public JDialog(Frame owner,
boolean mod)
Erzeugung eines JDialog-Objekts ohne Titel und dem Frame-(JFrame-)
Objekt owner als "Besitzer". Der Parameter mod bestimmt die Modalität :
modal, wenn true, nicht-modal, wenn false
public JDialog(Frame owner,
String tit,
boolean mod)
Erzeugung JDialog-Objekts mit dem Titel tit und dem Frame(JFrame-) Objekt owner als "Besitzer". Der Parameter mod bestimmt die
Modalität : modal, wenn true, nicht-modal, wenn false
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
public
public
public
public
public
Container getContentPane()
void setDefaultCloseOperation(int op)
void setJMenuBar(JMenuBar menu)
setTitle(String title)
*)
geerbt von
void dispose()
**) geerbt von
void pack()
**) geerbt von
Der Wert EXIT_ON_CLOSE für op ist nicht zulässig
Dialog
Window
Window
Einige weitere Memberfunktionen (geerbt von Dialog) :
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
26
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 ausgefü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) ausgibt 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-Schaltknö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.
27
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 ? ");
28
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 darstellen (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
SwingConstants.RIGHT
SwingConstants.LEFT
SwingConstants.TOP
SwingConstants.BOTTOM
(zentriert)
(rechtsbündig)
(linksbündig)
(obenbündig)
(untenbündig)
◇ JLabel-Objekte können nicht auf vom Benutzer ausgelöste Ereignisse (Eingaben) reagieren.
◇ Konstruktoren (Auswahl)
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
◇ Memberfunktionen (Auswahl)
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)
◇ 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.
29
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 Darstellungsbereichs festgelegt werden.
Default-Ausrichtung für Text und Bilder : horizontal rechtsbündig, vertikal zentriert
Explizite Festlegung der Ausrichtung : SwingConstants.CENTER
SwingConstants.RIGHT
SwingConstants.LEFT
SwingConstants.TOP
SwingConstants.BOTTOM
(zentriert)
(rechtsbündig)
(linksbündig)
(obenbündig)
(untenbündig)
◇ Im Unterschied zu JLabel-Objekten können JButton-Objekte (Schaltknöpfe !) vom Benutzer veranlasste Ereignisse 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)
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
◇ 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 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)
30
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 eingefügt bzw im Textfeld markiert und – ausgeschnitten oder kopiert – in das Clipboard eingefügt werden.
◇ Konstruktoren (Auswahl)
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
◇ Memberfunktionen (Auswahl)
Die meisten der nachfolgend aufgeführten Memberfunktionen sind von der Klasse JTextComponent geerbt.
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)
*) geerbt von JTextComponent (Package javax.swing.text)
31
Setzen der horizontalen Ausrichtung des
Textfeldes auf halign
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 ObjektErzeugung : 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 Clipboard 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 programm-initiierten Editierens dynamisch ändern.
◇ Es ist möglich, für ein JTextArea-Objekt die Anzahl der Zeilen und Spalten festzulegen. Diese dienen zur Ermittlung 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 Umbruch) 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 Textfenster 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,
int cols)
Erzeugung eines "leeren" JTextArea-Objekts,
Die Anzahl der Zeilen ist durch rows, die Anzahl der Spalten durch
cols festgelegt.
public JTextArea(String text,
int rows,
int cols)
Erzeugung eines JTextArea-Objekts, das mit text initialisiert ist,
Die Anzahl der Zeilen ist durch rows, die Anzahl der Spalten durch
cols festgelegt.
32
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
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,
int beg, int end)
Ersetzen des Textes zwischen den Positionen beg und end
durch den String str
*) geerbt von JTextComponent (Package javax.swing.text)
33
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);
}
}
34
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)
35
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 ausschnittsweise 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-ObjektErzeugung oder später mittels spezieller Memberfunktionen erfolgen.
Zur Festlegung stehen die folgenden – im implementierten Interface
javax.swing) definierten – Konstanten zur Verfügung :
- JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
- JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
- JScrollPane.VERTICAL_SCROLLBAR_ALWAYS
- JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS
- JScrollPane.VERTICAL_SCROLLBAR_NEVER
- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER
ScrollPaneConstants (Package
(vertikale Bildlaufleiste nur bei Bedarf sichtbar)
(horizontale Bildlaufleiste nur bei Bedarf sichtbar)
(vertikale Bildlaufleiste immer sichtbar)
(horizontale Bildlaufleiste immer sichtbar)
(vertikale Bildlaufleiste nie sichtbar)
(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)
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 GUIKomponenten-Objekt view eingebettet ist.
Beide Bildlaufleisten werden nur bei Bedarf dargestellt
public JScrollPane(Component view,
int vsbPol, int hsbPol)
Erzeugung eines JScrollPane-Objekts, in dem das GUIKomponenten-Objekt view eingebettet ist
Die Sichtbarkeit der Bildlaufleisten wird durch vsbPol (vertikal und hsbPol (horizontal) festgelegt
◇ Memberfunktionen (Auswahl)
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)
36
Einbettung des GUI-Komponenten-Objekts view
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);
}
}
37
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)
38
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);
}
}
39
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)
40
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)
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,
boolean select)
Erzeugung eines JCheckBox-Objekts, dessen AnfangsSelektionszustand 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,
boolean select)
Erzeugung eines JCheckBox-Objekts, dessen AnfangsSelektionszustand durch select festgelegt ist
(select==true : selektiert), mit dem Bild image versehen
public JCheckBox(String text,
Icon image)
Erzeugung eines nicht selektierten JCheckBox-Objekts,
mit dem Text text beschriftet und dem Bild image versehen
public JCheckBox(String text,
Icon image,
boolean select)
Erzeugung eines JCheckBox-Objekts, dessen AnfangsSelektionszustand durch select festgelegt ist
(select==true : selektiert), mit dem Text text beschriftet
und mit dem Bild image versehen
◇ Memberfunktionen :
Ein großer Teil der angebotenen Schnittstelle ist von der Klasse AbstractButton geerbt,
u.a. :
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
41
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 alternativer 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)
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 Anfangsboolean 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 Anfangsboolean select) Selektionszustand durch select festgelegt ist
(select==true : selektiert), mit dem Bild image versehen
public JRadioButton (String text,
Icon image)
Erzeugung eines nicht selektierten JRadioButton -Objekts,
mit dem Text text beschriftet und dem Bild image versehen
public JRadioButton (String text,
Erzeugung eines JRadioButton -Objekts, dessen AnfangsIcon image,
Selektionszustand durch select festgelegt ist
boolean select) (select==true : selektiert), mit dem Text text beschriftet
und mit dem Bild image versehen
◇ 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 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
42
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 zusammengefasst 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 :
public ButtonGroup()
Erzeugung eine neuen ButtonGroup-Objekts
◇ Memberfunktionen :
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>
getElements()
Rückgabe aller in der Gruppe enthaltenen AbstractButton(konkret JRadioButton-)Objekte
◇ 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.
43
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);
}
}
44
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 wiederum 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-LevelContainern 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)
public JPanel()
Erzeugung eines JPanel-Objekts
(Flow-Layout voreingestellt)
public JPanel(LayoutManager layout)
Erzeugung eines JPanel-Objekts mit dem durch layout
festgelegten Layout-Manager
◇ 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.
45
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);
}
}
46
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 ebenfalls 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 BoxLayout – 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
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)
◇ Statische Methoden zur Objekterzeugung
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
◇ Statische Methoden zur Erzeugung unsichtbarer GUI-Komponenten (Auswahl)
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()
47
Erzeugung eines Box.Filler-Objekts variabler
anpassbarer Höhe ( vertikale Füll-Komponente)
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);
}
}
48
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 EreignisKlassen (event objects) dargestellt.
Diese Ereignis-Objekte kapseln Informationen über das jeweilige Ereignis (z.B. die Ereignisquelle, spezielle Parameter, 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 Parameter ü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.
Ereignisquelle 1
event
Ereignisquelle 2
event
Event-Listener 1
Event-Listener 2
Event-Listener 3
event
Ereignisquelle 3
event
Event-Listener 4
◇ 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.
49
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
AWT
AWTEvent
(java.awt)
Swing
EventObject
(java.util)
ChangeEvent
ListSelectionEvent
CaretEvent
MenuEvent
(javax.swing.event) (javax.swing.event) (javax.swing.event) (javax.swing.event)
. . . weitere EventKlassen
ComponentEvent
(java.awt.event)
ActionEvent
(java.awt.event)
InputEvent
(java.awt.event)
ContainerEvent
(java.awt.event)
KeyEvent
(java.awt.event)
ItemEvent
(java.awt.event)
WindowEvent
(java.awt.event)
AncestorEvent
(javax.swing.event)
FocusEvent
(java.awt.event)
. . . weitere EventKlassen
. . . weitere EventKlassen
MouseEvent
(java.awt.event)
◇ 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 :
public Object getSource()
Ermittlung der ursprünglichen Ereignisquelle
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
50
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 :
GUI-Klasse
unterstützte Ereignis-Klasse
auslösende Aktionn
Component
ComponentEvent
FocusEvent
KeyEvent
MouseEvent
Position, Größe oder Sichtbarkeit wurden geändert
Focus wurde erhalten oder verloren
Tastatur wurde betätigt
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
ChangeEvent
Schaltknopf wurde betätigt
Zustand des Schaltknopfes hat sich geändert
JTextField
ActionEvent
CaretEvent
RET-Taste wurde betätigt
Cursorposition hat sich geändert
JTextArea
CaretEvent
Cursorposition hat sich geändert
JCheckBox
und
JRadioButton
ActionEvent
ChangeEvent
ItemEvent
Auswahlfeld wurde betätigt
Zustand des Auswahlfelds hat sich geändert
Selektionszustand hat sich geändert
JList
ListSelectionEvent
…
Selektion wurde geändert
◇ Memberfunktionen (Auswahl) einiger Ereignis-Klassen zur Informationsermittlung über das Ereignis :
▻ Klasse AWTEvent
public int getID()
Ermittlung der auslösenden Aktionsart (Klassenkonstante !)
▻ Klasse ActionEvent
public String getActionCommand()
Ermittlung der für das Ereignis festgelegten Aktionskennung
▻ Klasse ItemEvent
public Object getItem()
Ermittlung des vom Ereignis betroffenen Objekts
public int getStateChange()
Ermittlung des geänderten Zustands (selektiert oder nicht selektiert)
▻ Klasse WindowEvent
public Window getWindow()
Ermittlung des Fensters, das das Ereignis ausgelöst hat
51
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 :
Beispiel :
Zur Ereignis-Klasse AbcEvent existieren Listener-Interfaces AbcXyzListener
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.
52
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)
public void actionPerformed(ActionEvent e)
aufgerufen, wenn ein ActionEvent auftritt
▻ Interface ItemListener (Package java.awt.event)
public void itemStateChanged(ItemEvent e)
aufgerufen, wenn ein ItemEvent auftritt
▻ Interface WindowListener (Package java.awt.event), unvollständig
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
53
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
public abstract void
public abstract void
public abstract void
definiert drei unterschiedliche Methoden:
keyPressed(KeyEvent e)
keyReleased(KeyEvent e)
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.
54
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 Methoden 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 überschreiben.
◇ 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, implementieren.
Eine Listener-Klasse kann auch mehrere Listener-Interfaces implementieren und damit auf Ereignisse unterschiedlicher 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 Registrierungsfunktionen 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) :
public void addActionListener(ActionListener lis) Registrierung des Action-Listener-Objects lis
◆ 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 setActionCommand(String cmd)
55
Setzen der Aktionskennung cmd
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
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
/* Listing2802.java */
import java.awt.*;
import java.awt.event.*;
public class Listing2802
extends JFrame
implements KeyListener
{
public static void main(String[] args)
{
Listing2802 wnd = new Listing2802();
}
public Listing2802()
{
super("Nachrichtentransfer");
setBackground(Color.lightGray);
setSize(300,200);
setLocation(200,100);
setVisible(true);
addKeyListener(this);
}
public void paint(Graphics g)
{
g.setFont(new Font("Serif",Font.PLAIN,18));
g.drawString("Zum Beenden bitte ESC drücken...",10,50);
}
public void keyPressed(KeyEvent event)
{
if (event.getKeyCode() == KeyEvent.VK_ESCAPE) {
setVisible(false);
dispose();
System.exit(0);
}
}
public void keyReleased(KeyEvent event)
{
}
public void keyTyped(KeyEvent event)
{
}
}
Listing2802.java
56
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 EventListenerInterfaces 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
57
024
025
026
027
028
public void paint(Graphics g)
{
g.setFont(new Font("Serif",Font.PLAIN,18));
g.drawString("Zum Beenden bitte ESC drücken...",10,50);
}
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
58
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 mainMethode und dient lediglich dazu, die anderen beiden Klassen zu instanzieren. MainFrameGUI realisiert die GUIFunktionalitä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
59
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.
60
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);
}
}
61
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);
}
}
62
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
public
public
public
JList()
JList(Object[] listData)
JList(Vector listData)
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)
63
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);
64
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:
65
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);
66
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);
}
}
67
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.
68
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:
AbstractComponent
ConcreteComponent 1
ConcreteComponent 2
Container
Klassendiagramm eines Composite
Das folgende Listing skizziert dieses Design-Pattern am Beispiel einer einfachen Menüstruktur:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
/* Listing1013.java */
class MenuEntry1
{
protected String name;
public MenuEntry1(String name)
{
this.name = name;
}
public String toString()
{
return name;
}
}
69
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
70
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)
71
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 Darstellungen 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.
Publisher
-observers:Observer
+attach:Observer
+detach:Observer
+notify:void
0..n
observers
interface
Observer
+update:void
void notify()
{ for all o
in observers
o.update();
}
ConcretePublisher
ConcreteObserver
1
-subjState:State
publisher
+setState:void
+getState:State
-observState:State
-publisher:ConcretePublisher
+update:void
Abbildung 10.8: Klassendiagramm eines Observers
72
 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 BroadcastKommunikation. 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 PublisherObjekt enthalten
73
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
74
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
75
Herunterladen