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:

  • JTree
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

 

 

Home | Java | Forum | Media | Misc | Links | Contact | Sitemap | Search
© Kai Tödter 2008