|
Let’s swing!
Professionelle graphische
Benutzeroberflächen
mit den Java Foundation
Classes
Kai Tödter
Mit den Java Foundation
Classes (JFC) beziehungsweise dem darin enthaltenen Swing-Set wird die Stunde
Null der GUI-Entwicklung in Java eingeläutet. Swing bietet ein reichhaltiges
Angebot an sehr flexiblen GUI-Komponenten und wird die meisten Anforderungen
auch an professionelle GUIs abdecken. Dieser Artikel gibt eine kurze Einführung
in die zugrundeliegende Architektur und zeigt anhand einiger konkreter Beispiele,
wie einfach man mit Swing graphische Benutzeroberflächen erstellen kann.
Einführung
Grafische Benutzeroberflächen (engl. Graphical User Interfaces
= GUIs ) sind ein wichtiger Bestandteil von fast allen Software-Produkten. Die
Qualität der GUIs trägt dabei sehr zum Erfolg oder Mißerfolg
eines Produktes bei. Bisher konnten sich die GUIs von Java-Programmen kaum mit
denen von Programmen messen, die ein Betriebssystem spezifisches GUI API (Application
Programming Interface) benutzten. Der Grund hierfür ist offensichtlich:
Da Java betriebssystem-unabhängig sein soll, wurde für den ersten
Wurf des AWT (Abstract Window Toolkit) nur die Schnittmenge der gängigen
GUIs verwendet. Noch dazu wurde von außen ein enormer Druck auf die AWT-Entwickler
ausgeübt, die das komplette AWT in nur 5 Wochen auf die Beine stellen mußten.
Zum einen ist es erstaunlich, welch akzeptable Lösung in dieser kurzen
Zeit zu Stande kam, zum anderen ist es nicht verwunderlich, daß das AWT
niemanden wirklich begeistern konnte. Es war sogar der am meisten kritisierte
Teil des JDKs (Java Development Kit). Mit der kommenden Version 1.2 wird sich
die GUI-Programmierung in Java grundsätzlich ändern, denn mit den
Java Foundation Classes (JFC) wird unter anderem ein mächtiges Framework
mitgeliefert, das die GUI-Funktionalität des jetzigen AWT ersetzt und noch
dazu erheblich erweitert. Die erste Version des JDK 1.2 wird im Januar 1998
erwartet. Darin enthalten sind unter anderem die Java Foundation Classes, welche
aus 5 Paketen bestehen:
- Swing
Reichhaltige Menge von flexiblen GUI-Komponenten basierend auf
dem "Lightweight UI Frameswork" des JDK 1.1 [Tur97].
- Java 2D
Framework für die geräte-unabhängige 2D-Grafik,
Text und Bildverarbeitung. Das Java 2D API bietet dafür ein zweidimensionales
einheitliches Modell für Farben, räumliche Transformation und Anordnung.
Dieses Modell wird sowohl für Bildschirm wie auch Drucker benutzt, was
hochgradiges WYSIWIG (What You See Is What You Get) zur Folge hat.
- Drag and Drop
Plattformunabhängiges Drag & Drop zwischen Java und betriebssystemspezifischen
Applikationen (z.B zwischen OLE (Win32), CDE/Motif dynamic Protocol, MacOS und
JavaOS) sowie MIME-basierter Daten-Transfer.
- Accessibility
Erlaubt unterstützenden Technologien (z.B. Spracherkennung,
Braille-Terminals etc.) Informationen über User-Interface-Objekte zu bekommen,
z.B. über Layout, Hierarchie, Status, Größe etc.. Naturlich
können die Accessibility-Features auch zum Monitoring und Debuggen von
Java-Applikationen genutzt werden.
- AWT
Das Abstract Window Toolkit des JDK 1.1
Dieser Artikel beschäftigt
sich in erster Linie mit Swing bzw. mit dem AWT, wenn Swing auf dieses aufsetzt.
Die Entwickler von Swing setzten sich folgende Design-Ziele:
- Vereinheitlichung der
Java GUI APIs
- Die Menge der beinhalteten
Java-Komponenten sollte möglichst umfassend sein
- 100% pures Java und
leichtgewichtig
Abbildung 1: Swing-Demo
Wenn man die aktuelle Swing
Version 0.5.1 betrachtet, läßt sich jetzt schon feststellen, daß
Swing auf gutem Weg ist, diese Design-Ziele auch zu erreichen. Abbildung 1 zeigt
die mit Swing 0.5.1 mitgelieferte Demo, in der fast alle Swing-Komponenten auf
anschauliche Weise dargestellt werden. Bevor näher auf die Komponenten
eingegangen wird, erstmal ein kurzer Blick auf die zugrundeliegende Architektur.
Architektur

Abb. 2: MVC-Architektur
Abb. 3: Modifiziertes MVC
Die Gesamt-Architektur
basiert auf 2 grundlegenden Design-Techniken, dem JavaBeans-Modell (für
Properties, Persistenz und event-basierter Kommunikation) und einem neuartigem
"Pluggable Look & Feel"-Mechanismus. Dafür wurde ein weiteres grundlegendes
Architektur-Prinzip genutzt, eine modifizierte Version der bekannten Model-View-Controller-Architektur
(MVC). Im klassischen Model-View-Controller-Design besteht jede Komponente aus
3 Teilen: dem Model, dem View und dem Controller. Abbildung
2 zeigt diese 3 Teile und ihre Beziehungen. Im Model-Teil einer MVC-basierten
Komponente befinden sich die Werte bzw. Eigenschaften der Komponente, welche
ihre Semantik definieren. Bei einem Schieberegler könnte das zum Beispiel
der aktuelle Wert, die Minimal- und die Maximal-Position sein. Im Controller-Teil
der Komponente werden Benutzer-Aktionen ausgewertet und an das Modell weitergeleitet.
In unserem Beispiel z.B. das Verschieben des Reglers mit der Maus. Der View-Teil
ist schließlich für die visuelle Darstellung der Komponente (z.B.
auf dem Bildschirm) verantwortlich. Die Vorteile einer MVC-basierten Architektur
liegen klar auf der Hand, durch die Trennung der einzelnen Teile kann z.B. das
Aussehen einer Komponente verändert werden, ohne Ihr Verhalten zu modifizieren.
Andererseits muß für neue Benutzer-Ereignisse nur der Controller-Teil
verändert werden. Es gibt natürlich noch viele weitere Vorteile, auf
die an dieser Stelle aber nicht näher eingegangen wird. Aus der strikten
Trennung von View und Controller ergibt sich allerdings auch ein Problem: Die
Kommunikatioen zwischen dem View- und dem Controller-Teil einer
Komponente kann sehr schnell äußerst komplex und unüberschaubar
werden. Diese Erfahrung hat wahrscheinlich jeder schon gemacht, der versucht
hat, ein komplexe Komponente nach der "reinen" MVC-Lehre zu realisieren. Aus
diesem Grund modifizierten die Swing-Entwickler die klassische MVC-Architektur
und faßten den View- und den Contoller-Teil zu einem View-Controller
zusammen. Abbildung 3 veranschaulicht die modifizierte MVC-Architektur.
Pluggable Look and Feel
Eine der herausragenden Eigenschaften von Swing ist das "Pluggable
Look and Feel". Das besondere daran ist, daß es auch zur Laufzeit eines
Programmes geändert werden kann. So könnte man z.B. zur Laufzeit zwischen
einem Windows 95- oder Motif-Look umschalten. Da macht z.B. Sinn, wenn ein Benutzer
an das Windows Look & Feel (L&F) seiner Applikation gewöhnt ist
und dieses auch auf einer Solaris-Maschine haben will, ohne die Applikation,
die vielleicht immer läuft, herunterfahren zu müssen. Eine weitere
wichtige Anwendungsmöglichkeit ist, daß die grafische Ausgabe der
Komponenten an die Eigenschaften bestimmter Ausgabegräte angepaßt
werden kann, z.B. an einen kleinen Schwarz-Weiß-Bildschirm eines PDAs
(Personal Digital Assistant). Hier eine Auflistung der wesentlichen Merkmale
von Swings Pluggable Look and Feel:
- Das Look & Feel
einer Komponente kann vollständig und einfach ersetzt werden
- Für jede Komponente
steht ein Default Look & Feel bereit, welches erweitert oder modifiziert
werden kann
- Das Look & Feel
von Komponenten läßt sich explizit überschreiben, entweder
für die gesamte Applikation oder für einzelne Komponenten
Abb. 4: Look & Feel
Auf die Details der zugrundeliegenden
Architektur wird dieser Stelle nicht weiter eingegangen, programmiertechnisch
ist es jedoch eine Kleinigkeit, Applikationen zu entwickeln, welche zur Laufzeit
zwischen vorhandenen Look & Feels umschalten können (Siehe unten).
Schwieriger und sehr viel anspuchsvoller ist es allerdings, ein eigenes Look
& Feel zu entwickeln. Diese Arbeit sollte man lieber Experten überlassen
und die mitgelieferten Look & Feels nutzen. Vorstellbar ist allerdings,
daß eine große Firma z.B. ihr eigenes Corporate-Design entwickelt
und alle im Intranet verfügbaren Applikationen dieses Look & Feel besitzen.
Noch ein letztes Wort zu den mitgelieferten Look & Feels. Geplant sind Windows95,
Motif und ein eigenes Java Look & Feel. Wie die rechtliche Seite bezüglich
des Windows Look & Feels aussieht, wird die Zukunft zeigen. Abbildung 4
zeigt die gleiche Mini-Applikation, einmal mit Windows95, einmal mit Rose Look
& Feel. Die Umschaltung des Look & Feels für die gesamte Applikation
kann durch paar wenige Code-Zeilen realisiert werden. Das folgende Code-Beispiel
zeigt die Implementierung des ActionListeners für die beiden Radio-Buttons.
class
RadioListener implements ActionListener {
public void actionPerformed( ActionEvent e
) {
String lnfName = null;
//
Aufgrund des gedückten Buttons das gewünschte Look & Feel setzen
if ( e.getActionCommand() == rose ) {
lnfName = "com.sun.java.swing.rose.RoseLookAndFeel";
}
else {
lnfName = "com.sun.java.swing.basic.BasicLookAndFeel";
}
try
{
UIManager.setLookAndFeel(
lnfName );
// Unschalten des Look
& Feels für das Applikations-Frame
SwingUtilities.updateComponentTreeUI(
frame );
frame.pack();
}
catch ( Exception exc ) {
System.err.println(
"could not load LookAndFeel: " + lnfName );
}
}
}
Komponenten
Bevor auf einige Swing-Komponenten im Detail eingegangen wird,
hier erstmal ein kleiner Überblick in Form einer Klassen-Hierarchie. Abbildung
5 zeigt den Teil von Swing, welcher die aus dem AWT 1.1 bekannten Komponenten
ersetzt. Wie anfangs schon erwähnt, ist Swing in 100% purem Java implementiert.
Dies schließt sowohl die Verwendung von Native-Methoden, wie natürlich
auch die (weitgehende) Verwendung von Peers, also die Abbildung von Java-Komponenten
auf betriebssystem-spezifische Komponenten, aus. Das hat den entscheidenen Vorteil,
daß sich alle Swing-Komponenten des gleichen Look & Feels auf allen
Plattformen gleich verhalten und gleich aussehen.
Abb 5: Swing-Komponenten, die die AWT 1.1 Komponenten ersetzen
Basis aller Swing-Komponenten
ist die Klasse JComponent, welche eine Reihe von Merkmalen besitzt:
- Pluggable Look &
Feel
- Kann mit anderen Komponenten
kombiniert und erweitert werden
- Reichhaltige Tastatur-Behandlung
(Short Cuts, Accelerators, Tabs, etc.)
- Mit Hilfe von Action-Objekten
können gleiche Aktivitäten von verschiedenen Komponenten genutzt
werden
- Borders, also Begrenzungen
verschiedenster Art, z.B. Linien, 3D-Effekte etc.
- Die Möglichkeit,
die bevorzugte, minimale und maximale Größe zu setzen
- Tooltips, also erklärender
Text, wenn man die Maus über eine Komponente bewegt
- Zeitlupenartiger Aufbau
der Grafik, sinnvoll zum Debuggen der Looks
- Accessibility Unterstützung
(Siehe oben)
- Unterstützung
von Internationalisierbarkeit
Abbildung 6 zeigt eine (nicht
ganz vollständige) Hierarchie der restlichen Swing-Komponenten. Doch bevor
die erste von JComponent abgeleitete Klasse vorgestellt wird, erfolgt ein kurzer
Abstecher in die Mechanismen zum Darstellen von Bildern, bzw. Icons. Diese können
nämlich von vielen Swing-Komponenten (wie z.B. Labels oder Buttons) benutzt
werden. Alle Swing-Icons müssen das folgende Interface implementieren:
Abbildung 6: Swing-Komponenten
public
interface Icon
{
void paintIcon( Component c, Graphics g, int
x, int y );
int getIconWidth();
int getIconHeight();
}
Eine Implementierung dieses
Interfaces liefert die Klasse ImageIcon. Um z.B. ein ImageIcon aus einem GIF-Bild
zu erzeugen, genügt folgende Code-Zeile:
Icon picture
= new ImageIcon( "picture.gif" );
Das Besondere an ImageIcons
gegenüber den Images aus dem AWT ist, daß diese synchron geladen
werden und serialisierbar sind.
Labels und Buttons
Doch nun zu einer der einfachsten Swing-Komponente, dem Label,
was durch die Klasse JLabel implementiert wird. Das Besondere an Labels ist,
daß sie sowohl ein Icon wie auch einen Text beinhalten können. Text
und Bild können dabei beliebig zueinander positioniert werden und auch
die Abstände zum Label-Rand sind frei wählbar. Erwähnenswert
ist noch, daß JLabel kein Modell besitzt, JLabel.getModel() liefert also
null zurück. Der folgende Source-Code gibt ein Beispiel für das Erzeugen
eines Labels mit Text und Icon:
JLabel
testLabel = new Jlabel( "TestLabel" );
Icon labelIcon = new ImageIcon( "LabelIcon.gif" );
testLabel.setIcon( labelIcon );
Neben den Labels sind wahrscheinlich
die Buttons, in Swing implementiert durch JButton, die am häufigsten gebrauchten
Komponenten. Natürlich können diese auch sowohl Text, wie auch ein
Icon enthalten und verfügen auch über Positionierungsmechanismen.
Erwähnenswert ist, daß Buttons noch 3 zusätzliche Icons haben
können:
- Ein "Rollover"-Icon,
das angezeigt wird, wenn sich die Maus über dem Button befindet. Dieser
Mechanismus läßt sich z.B. dazu verwenden, um Netscape Communicator
ähnliche Tool Bars zu entwickeln.
- Ein "Pressed"-Icon,
das angezeigt wird, wenn der Button gedrückt wird.
- Ein "Disabled"-Icon,
welches angezeigt wird, wenn der Button disabled, also nicht benutzbar, wird.
Erwähnenswährt ist noch, daß ein farbiges Icon automatisch
schwarz-weiß gerendert wird, sollte der Button disabled werden und kein
explizites "Disabled"-Icon gesetzt sein.
Hier ein Tip: Wenn ein Button
ein animiertes GIF-Bild enthalten soll, genügt es, einen ImageObserver zu
setzen, z.B.
ImageIcon
animatedImage = new ImageIcon( "animated.gif" );
JButton animatedButton = new JButton( animatedImage );
animatedImage.setImageObserver( animatedButton );
Abbildung 7: Swing-Button-Hierarchie
Neben dem "normalen" Button
bietet Swing natürlich auch JCheckBox und JRadioButton. Abbildung 7 zeigt
die Swing-Button-Hierarchie.
Menüs und Toolbars
Natürlich werden sowohl Menüs wie auch Toolbars von
Swing unterstützt. Zum Erstellen von Menüs bietet Swing folgende Komponenten:
- JMenuBar
Eine Menü-Leiste, also ein Container für Menüs.
- JMenuItem
Ein Eintrag in einem Menü. Diese Button-ähnliche Komponente
feuert Action-Events, wenn sie vom Benutzer selektiert wird.
- JCheckboxMenuItem
Ein CheckBox-ähnlicher Menü-Eintrag.
- JRadioButtonMenuItem
Ein RadioButton-ähnlicher Menü-Eintrag.
- JPopupMenu
Ein Popup-Menü, daß Menü-Einträge und andere
Komponenten beinhalten kann.
- JMenu
Eine von JMenuItem abgeleitete Komponente, die automatisch ein
Popup-Menü aufklappt. Nützlich zum Erzeugen von Untermenüs.
Das Besondere an Swings Toolbars
ist, daß diese "Floatable and Dockable" sind. Das bedeutet, man kann eine
Toolbar mit der Maus aus ihrem Kontext herausziehen und auf dem Desktop fallenlassen.
Als Resultat dieser Aktion erhält man ein neues Fenster, welches die Toolbar
enthält. Dieses Fenster kann wiederum mit der Maus über einer beliebigen
Komponente mit Border-Layout fallengelassen werden. Schon wird die Toolbar dort
eingefügt. Abbildung 8 zeigt ein Beispiel für ein Menü und 2 Toolbars
(Das Tapedeck-artige Steuer-Panel ist auch eine Toolbar).
Listen
Swings Klasse JList ersetzt die List-Klasse des AWT. Listen von
Strings lassen sich auf sehr einfache Weise erstellen, zum Beispiel:
String
label [] = { "Rot", "Grün", "Blau" };
JList list = new JList( label );
Um die Liste scrollbar
zu machen, muß diese noch in eine ScrollPane eingebettet werden:
ScrollPane
pane = new ScrollPane();
pane.add ( list );
Abbildung 8: Swing-Applikation mit Menü, 2 Toolbars und einer
Liste mit Tabellen-Header
Anhand von einer Liste
läßt sich aber auch sehr gut MVC-Design demonstrieren. Abbildung
8 zeigt z.B. eine Liste, deren View-Teil an einen Tabellen-Header angebunden
ist. Als Demonstrator für einfaches MVC-Design in Swing soll nun eine Liste
implementiert werden, die beliebige Farben darstellen kann. Für jeden Eintrag
der Liste soll ein kleines Rechteck in der entsprechenden Farbe gezeichnet und
dahinter die Rot-, Grün- und Blau-Komponenten der Farbe ausgegeben werden.
Als Modell für diese Liste reicht ein Vektor von Color-Objekten, man kann
also das DefaultListModell verwenden, was genau das Gewünschte liefert.
Nicht ganz so trivial ist die Darstellung der Listen-Elemente, also ein Teil
des Views. Da ein Icon und ein Text dargestellt werden sollen, bietet sich ein
JLabel als Basis für den benötigten ListCellRenderer an. Cell-Renderer
sind ein gebräuchlicher Mechanismus in Swing, um die grafische Darstellung
von Komponenten-Teilen, wie z.B. den Einträgen (Zellen) in Listen, Tabellen,
Bäumen etc., zu bestimmen. Allen Cell-Renderern gemeinsam ist, daß
sie das jeweilige Cell-Renderer-Interface implementieren müssen, wobei
natürlich Default-Cell-Renderer (meistens JLabel) von Swing bereitgestellt
werden. Da hier allerdings die Darstellung von Farben implementiert werden soll,
wird ein neuer Renderer (im Beispiel ColorCellRenderer) gebraucht. Wie schon
oben erwähnt, implementiert dieser das ListCellRenderer-Interface und ist
von der Klasse JLabel abgeleitet. Für das farbige Rechteck wird ein Icon-Interface
implementiert, welches dann vom Renderer benutzt werden kann. Es folgt der komplette
Source-Code für die Farben-Liste:
//
Swing package
import com.sun.java.swing.*;
// AWT für Layout
und WindowListener
import java.awt.*;
import java.awt.event.*;
/*
* ColorList, eine einfache Farbenliste
*/
public class ColorList
extends JPanel
{
static JFrame frame; // Frame für das
Hauptprogramm
public
ColorList()
{
super( true ); // Double-Buffering
setLayout( new BorderLayout()
);
// Als Listen-Modell nehmen wir das Default-Modell,
// was einem Vektor
von Objekten entspricht
DefaultListModel model
= new DefaultListModel();
// Zur Demonstration werden einige Farben ins Modell gepackt
model.addElement( Color.blue
);
model.addElement( Color.green
);
model.addElement( Color.red
);
model.addElement( Color.black
);
model.addElement( Color.cyan
);
model.addElement( Color.gray
);
model.addElement( Color.lightGray
);
model.addElement( Color.yellow
);
// Nun erzeugen wir eine Listbox unserem Modell als Grundlage
JList listBox = new
JList( model );
// Nur unser Cell-Renderer weiß, wie wir die Farben dargestellt
// haben wollen
listBox.setCellRenderer(
new ColorCellRenderer( listBox ) );
// Damit die Liste scrollbar ist, müssen wir sie noch in
// eine JScrollPane
einbetten
JScrollPane scrollPane
= new JScrollPane( listBox );
add( "Center", scrollPane);
}
/*
* Unser ColorCellRenderer soll die Farben folgendermaßen
darstellen:
* ein in der Farbe bemaltes kleines Quadrat
+ die Rot-, Grün- und
* Blau-Anteile als Text. Als Basis nehmen wir
dazu ein JLabel, was
* ja schon Icon und Text bietet.
*/
class
ColorCellRenderer extends JLabel implements ListCellRenderer
{
JList listBox; // unsere
Listbox
// dunkles Blau zum
Selektieren
Color highlightColor
= new Color( 0, 0, 128 );
ColorCellRenderer(
JList listBox )
{
// Damit beim Selektieren der Hintergrund auch blau wird
setOpaque( true );
this.listBox = listBox; // unsere Listbox
}
/*
* Wichtigste Methode
im ListCellRenderer-Interface
*/
public Component getListCellRendererComponent
(
JList list, // die Liste
Object value, // das zu rendernde Objekt im Modell, hier
// also eine Farbe
int index, // der Index innerhalb der Liste
boolean isSelected, // true, wenn das Listenelement selektiert
ist
boolean cellHasFocus // true, wenn die Zelle den Fokus hat
)
{
Color color = (Color)value; // unsere Farbe
if( listBox.isSelectedIndex( index ) )
{
// wenn selektiert, Hintergrung blau und Text weiß
setBackground(highlightColor);
setForeground(Color.white);
}
else
{
// ansonsten Hintergrund weiß und TExt schwarz
setBackground(Color.white);
setForeground(Color.black);
}
// Als Label-Text die Rot-, Grün- und Blau-Anteile
setText( " " + color.getRed() + ":" + color.getGreen()
+ ":" + color.getBlue() );
// Als Icon ein Rechteck in unserer Farbe
setIcon( new ColorIcon( color ) );
return this;
}
/*
* Da ein Label
ein Icon braucht, implementieren wir das farbige
* Rechteck als
16*16 großes Icon.
*/
class ColorIcon implements
Icon
{
ColorIcon( Color color )
{
this.color = color;
}
public int getIconWidth()
{
return 16;
}
public int getIconHeight()
{
return 16;
}
public void paintIcon( Component c, Graphics g, int x, int y)
{
// Farbe setzen und Rechteck zeichnen
g.setColor( color );
g.fill3DRect( 2, 2, 12, 12, true );
}
private Color color;
}
}
/*
* Das Haupt-Programm
*/
public static void main( String s[] )
{
// Exit an das Schließen
des Fensters binden
WindowListener l =
new WindowAdapter() {
public void windowClosing(
WindowEvent e ) { System.exit(0); }
};
// Frame erzeugen und darstellen
frame = new JFrame("Color
List");
frame.addWindowListener(
l );
frame.add( "Center",
new ColorList() );
frame.pack();
frame.setVisible( true
);
}
}
Als Ausgabe dieses kleinen
Programms erhält man eine scrollbare Liste von Farben:
Abbildung 9: Farben-Liste
Bäume
Wie alle der komplexeren Swing-Komponenten basieren auch die Bäune
auf der modifizierten MVC-Architektur. Um mit Bäumen umzugehen, braucht
man ein paar Klassen bzw. Interfaces:
Die eigentliche Baum-Komponente
- DefaultTreeModel
Ein Default-Modell, welches Objekte, die das TreeNode-Interface
implenemtieren, zur Modellierung benutzt. DefaultTreeModel implementiert das
TreeModel-Interface.
- DefaultMutableTreeNode
Eine DefaultMutableTreeNode ist eine Implementierung der Interfaces
MutableTreeNode und TreeNode und stellt einen Standard-Baum-Knoten dar, der
universell eingesetzt werden kann.
- DefaultTreeSelectionModel
Ein Default-Selektions-Modell, welches ausschließlich darauf
reagiert, wenn sich der im Baum selektierte Pfad (siehe unten) ändert.
- TreeSelectionListener
Wenn neue Selektions-Funktionalität erzeugt werden soll,
muß dieses Interface implementiert und dem TreeSelectionModel übergeben
werden.
- JTreePath
Ein Pfad von der Wurzel des Baumes zu einem bestimmten Knoten.
Natürlich ist es oft
sinnvoll, eigene Implementierungen der geforderten Interfaces zu schreiben, bzw.
von den existierenden Komponenten abzuleiten. In vielen Fällen werden die
von Swing bereitgestellten Defaults allerdings ausreichen. Es folgt ein kurzes
Beispiel, wie man einen kleinen Baum erzeugt und den Pfad der einzelnen Knoten
beim Selektieren ausgibt:
import
com.sun.java.swing.*;
import com.sun.java.swing.tree.*;
import com.sun.java.swing.event.*;
import java.awt.*;
import java.awt.event.*;
/*
* SimpleTree, ein einfacher Baum
*/
public class SimpleTree
extends JPanel
{
static JFrame frame; // Frame für das
Hauptprogramm
public SimpleTree()
{
super( true ); // Double-Buffering
setLayout( new BorderLayout()
);
// Erzeuge den Demo-Baum
DefaultMutableTreeNode
root = new DefaultMutableTreeNode( "Root" );
for( int n = 1; n <
4; n++ )
{
DefaultMutableTreeNode node =
new DefaultMutableTreeNode( "Node " + n );
root.add( node );
for( int i = 1; i< 4; i++ )
node.add( new DefaultMutableTreeNode( "Leaf " + ((n-1)*3+i ) ) );
}
// Erzeuge Default-Baum-Modell mit root als Wurzel
DefaultTreeModel model
= new DefaultTreeModel( root );
// Erzeuge Baum mit model als Modell
JTree tree = new JTree(
model );
// Hole das Selektions-Modell vom Baum
// und füge unseren
Listener hinzu
DefaultTreeSelectionModel
selectionModel
= ( DefaultTreeSelectionModel ) tree.getSelectionModel();
selectionModel.addTreeSelectionListener(
new SimpleTreeSelectionListener() );
// Damit der Baum scrollbar ist, müssen wir ihn noch in
// eine JScrollPane
einbetten
JScrollPane scrollPane
= new JScrollPane( tree );
add( "Center", scrollPane);
}
/*
* Einfacher Selektions-Listener, der den selektierten
Baum-Pfad ausgibt
*/
class SimpleTreeSelectionListener implements
TreeSelectionListener
{
public void valueChanged(
TreeSelectionEvent e )
{
// Pfad aus Event holen und ausgeben
TreePath path = e.getNewLeadSelectionPath();
System.out.println( path );
}
}
/*
* Das Haupt-Programm
*/
public
static void main( String s[] )
{
// Exit an das Schließen
des Fensters binden
WindowListener l =
new WindowAdapter() {
public void windowClosing(
WindowEvent e ) { System.exit(0); }
};
// Frame erzeugen und darstellen
frame = new JFrame(
"Simple Tree" );
frame.addWindowListener(
l );
frame.add( "Center",
new SimpleTree() );
frame.pack();
frame.setVisible( true
);
}
}
Die beiden Abbildungen
zeigen unser Beispiel und einen Baum mit eigenen Icons.
Weitere Komponenten
Die bisher vorgestellte Komponenten gehörten alle zu den
Swing-Basics. Weitere Komponenten ausführlich vorzustellen, würde
den Rahmen dieses Artikels sprengen, allein für die Tabellen-Komponente
JTable könnte man einen kompletten eigenen Artikel spendieren. Swing bietet
auf jeden Fall noch eine Vielzahl gängiger GUI-Komponenten und Utility-Klassesn
wie z.B. Combo Boxen, Slider, Spinner, Splitbare Fenster, Tooltips, Standard-Dialoge
( z.B. ColorChooser) etc., die einen sehr großen Bereich in Punkto GUI
abdecken.
Beans
Die meisten Swing-Komponenten sind als JavaBeans konzipiert. Leider
kann man die aktuelle Version 0.5.1 noch nicht so ohne weiteres in gängigen
Bean-Containern wie z.B. der BeanBox ausprobieren. Das Hauptproblem daran ist,
daß im Swing JAR-File zwar die nötigen BeanInfos etc. enthalten sind,
diese aber in einem eigenen Package untergebracht sind und somit von den meisten
Tools nicht gefunden werden. Da das Packen von BeanInfos in eigene Packages
durchaus Sinn macht, werden wohl alle Tool-Hersteller nachziehen müssen.
Weitere Probleme kann die Verwendung des Model-View-Controller-Paradigmas bereiten.
Sowie man eigene View- oder Modell-Komponenten verwendet, muß man eigenen
Source-Code an die entsprechenden Teile der visuellen Komponenten anhängen,
was zur Zeit von fast allen Bean-fähigen IDEs nur unzureichend unterstützt
wird. Anderseits ist es natürlich sehr sinnvoll, Beans zu bauen, welche
intern Swing-Komponenten verwenden.
Dokumentation und Download
Die bisher verfügbare Swing-Dokumentation ist erstaunlich
gut, wenn man bedenkt, daß es sich ja noch um einen Preview handelt. Neben
dem eigentlichen Swing, das zur Zeit aus den beiden JAR-Files swing.jar und
rose.jar besteht, bekommt man eine komplette API-Dokumentation, Überblick,
Architekturbeschreibung etc. im HTML-Format. Um Swing downloaden zu können,
muß man Mitglied der Java Developer Connection (JDC) sein, was uneingeschränkt
für jeden Java-Entwickler zu empfehlen ist. Die Mitgliedschaft ist kostenlos
und jeder, der Zugriff auf das WWW hat, kann sich unter http://www.javasoft.com/jdc
registrieren. Nach dem Registrieren kann man sich einloggen und findet Swing
unter "Early Access". Zum Schluß noch ein kleiner Tip: Beim Login in die
JDC muß darauf geachtet werden, daß der WWW-Browser Cookies akzeptiert,
sonst klappt es nicht!
Fazit
Mit den JFC beziehungsweise Swing wird die Stunde Null der GUI-Entwicklung
in Java eingeläutet. Swing bietet ein reichhaltiges Angebot an sehr flexiblen
GUI-Komponenten und wird die meisten Anforderungen auch an professionelle GUIs
abdecken. Durch sein "Pluggable Look & Feel" ist es möglich, sowohl
plattformspezifische (z.B. Windows95) wie auch eigene Look & Feels zu implementieren,
die sogar zur Laufzeit umgeschaltet werden können. Wegen dieser und anderer
Features wird Swing sicherlich viele Freunde finden und es ist endlich möglich,
mit Java-Standard-Komponenten ansprechende und professionelle GUIs zu erstellen!
Literatur und Links
[Swing] Swing, http://java.sun.com/products/jdk/awt/swing
[Tur97] Volker Turau, Lightweight-Komponenten in Java 1.1,
in:
Java SPEKTRUM, Juli/August 1997
|