Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage
<< | < | > | >> | API | Kapitel 35 - Swing: Grundlagen

## 35.2 Ein einführendes Beispiel

- 35.2 Ein einführendes Beispiel
  - 35.2.1 Das Beispielprogramm
  - 35.2.2 Beschreibung des Beispielprogramms
    - Die import-Anweisungen
    - JFrame
    - JPanel
    - JLabel
    - JTextField
    - Tooltips und Umrandungen
    - JList und JScrollPane
    - JButton
    - Umschalten des Look-and-Feel

### 35.2.1 Das Beispielprogramm

In diesem Abschnitt soll ein einfaches Beispielprogramm vorgestellt werden. Es handelt sich um eine einfache (und weitgehend sinnfreie) Swing-Anwendung mit einem Hauptfenster, in dem drei Gruppen von Komponenten untergebracht sind:

- Ganz oben befindet sich ein Panel mit einem Label und einem Textfeld, in dem ein Name eingegeben werden kann. Das Label besitzt neben seiner Beschriftung ein Icon mit einem kleinen blauen Pfeil.
- In der Mitte besitzt das Programm eine Liste, aus der ein Monatsname ausgewählt werden kann.
- Unten befindet sich ein Panel mit drei Buttons, mit denen zwischen den drei vordefinierten Look-and-Feels umgeschaltet werden kann.

Die beiden Panels wurden mit einer Umrandung versehen, und alle aktiven Elemente zeigen Tooltips an, wenn man mit dem Mauszeiger darauf zeigt. Durch Drücken auf den Schließen-Button in der Titelleiste kann das Programm beendet werden. Die übrigen Dialogelemente besitzen - neben ihrem Standardverhalten - keinerlei zusätzliche Funktionalität.

Abbildung 35.1 zeigt das Beispielprogramm mit dem Standard-Look-and-Feel von Java-Programmen (das auch als Metal-Look-and-Feel bezeichnet wird):

Abbildung 35.1: Das Beispielprogramm im Metal-Look-and-Feel

Oben links ist das Label "Name" mit seinem zugeordeten Icon zu erkennen. In das Textfeld wurde bereits der String "Meier, Karl-Friedrich" eingetragen. In der Liste ist der Monat Juni ausgewählt, und ihre Tooltips werden angezeigt, weil der Mauszeiger über der Liste verweilt. Die beiden Panels haben eine zusätzliche Umrandung, die vom Programm explizit hinzugefügt wurde.

Durch Drücken der Buttons kann das Look-and-Feel umgeschaltet werden. Abbildung 35.2 zeigt das Programm mit aktiviertem Motif-, Abbildung 35.3 mit aktiviertem Windows-Look-and-Feel.

|  | Während das Metal-Look-and-Feel für Swing neu entwickelt wurde, versuchen die beiden anderen, die speziellen Eigenschaften der korrespondierenden Fenstersysteme nachzuahmen. In der Praxis gelingt ihnen das mit wechselndem Erfolg. Insbesondere Anwender, die sehr an eines der beiden Fenstersysteme gewöhnt sind, werden viele kleine Abweichungen in der Swing-Implementierung feststellen. Zu bedenken ist auch, daß einige der Look-and-Feels aus Lizenzgründen nur auf ihren Originalplattformen zur Verfügung stehen (z.B. das Windows- und das Mac-Look-and-Feel). |  |
Hinweis

Abbildung 35.2: Das Beispielprogramm im Motif-Look-and-Feel

Abbildung 35.3: Das Beispielprogramm im Windows-Look-and-Feel

### 35.2.2 Beschreibung des Beispielprogramms

Zunächst wollen wir uns den Quellcode des Beispielprogramms ansehen. Er besteht aus der Klasse für das Hauptfenster, die lediglich einen parameterlosen Konstruktor und die Methode `actionPerformed` enthält. Der Programmcode ähnelt den Beispielen, die wir zum AWT gesehen haben:

    001 /* Listing3501.java */
    002
    003 import java.awt.event.*;
    004 import java.awt.*;
    005 import javax.swing.*;
    006
    007 public class Listing3501
    008 extends JFrame
    009 implements ActionListener
    010 {
    011   private static final String[] MONTHS = {
    012     "Januar",    "Februar", "März",     "April",
    013     "Mai",       "Juni",    "Juli",     "August",
    014     "September", "Oktober", "November", "Dezember"
    015   };
    016
    017   public Listing3501()
    018   {
    019     super("Mein erstes Swing-Programm");
    020     //Panel zur Namenseingabe hinzufügen
    021     JPanel namePanel = new JPanel();
    022     JLabel label = new JLabel(
    023       "Name:",
    024       new ImageIcon("triblue.gif"),
    025       SwingConstants.LEFT
    026     );
    027     namePanel.add(label);
    028     JTextField tf = new JTextField(30);
    029     tf.setToolTipText("Geben Sie ihren Namen ein");
    030     namePanel.add(tf);
    031     namePanel.setBorder(BorderFactory.createEtchedBorder());
    032     getContentPane().add(namePanel, BorderLayout.NORTH);
    033     //Monatsliste hinzufügen
    034     JList list = new JList(MONTHS);
    035     list.setToolTipText("Wählen Sie ihren Geburtsmonat aus");
    036     getContentPane().add(new JScrollPane(list), BorderLayout.CENTER);
    037     //Panel mit den Buttons hinzufügen
    038     JPanel buttonPanel = new JPanel();
    039     JButton button1 = new JButton("Metal");
    040     button1.addActionListener(this);
    041     button1.setToolTipText("Metal-Look-and-Feel aktivieren");
    042     buttonPanel.add(button1);
    043     JButton button2 = new JButton("Motif");
    044     button2.addActionListener(this);
    045     button2.setToolTipText("Motif-Look-and-Feel aktivieren");
    046     buttonPanel.add(button2);
    047     JButton button3 = new JButton("Windows");
    048     button3.addActionListener(this);
    049     button3.setToolTipText("Windows-Look-and-Feel aktivieren");
    050     buttonPanel.add(button3);
    051     buttonPanel.setBorder(BorderFactory.createEtchedBorder());
    052     getContentPane().add(buttonPanel, BorderLayout.SOUTH);
    053     //Windows-Listener
    054     addWindowListener(new WindowClosingAdapter(true));
    055   }
    056
    057   public void actionPerformed(ActionEvent event)
    058   {
    059     String cmd = event.getActionCommand();
    060     try {
    061       //PLAF-Klasse auswählen
    062       String plaf = "unknown";
    063       if (cmd.equals("Metal")) {
    064         plaf = "javax.swing.plaf.metal.MetalLookAndFeel";
    065       } else if (cmd.equals("Motif")) {
    066         plaf = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
    067       } else if (cmd.equals("Windows")) {
    068         plaf = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
    069       }
    070       //LAF umschalten
    071       UIManager.setLookAndFeel(plaf);
    072       SwingUtilities.updateComponentTreeUI(this);
    073     } catch (UnsupportedLookAndFeelException e) {
    074       System.err.println(e.toString());
    075     } catch (ClassNotFoundException e) {
    076       System.err.println(e.toString());
    077     } catch (InstantiationException e) {
    078       System.err.println(e.toString());
    079     } catch (IllegalAccessException e) {
    080       System.err.println(e.toString());
    081     }
    082   }
    083
    084   public static void main(String[] args)
    085   {
    086     Listing3501 frame = new Listing3501();
    087     frame.setLocation(100, 100);
    088     frame.pack();
    089     frame.setVisible(true);
    090   }
    091 }
| Listing3501.java

Listing 35.1: Ein einfaches Swing-Beispielprogramm

|  | In vielen Beispielen in diesem Buch wird der Einfachheit halber die in Abschnitt 23.2.4 vorgestellte Klasse `WindowClosingAdapter` verwendet, um einen Listener zum Schließen des Fensters zu registrieren. Damit ein solches Beispiel sich kompilieren läßt, muß die Datei WindowClosingAdapter.java im aktuellen Verzeichnis vorhanden sein. Sie befindet sich auf der CD-ROM zum Buch oder in Listing 23.2. |  |
Hinweis

#### Die import-Anweisungen

Im Gegensatz zu AWT-Programmen besitzt unser Beispielprogramm keine Anweisung, um das Paket `java.awt` zu importieren. Da alle Swing-Komponenten in `javax.swing` und seinen Unterpaketen stecken, benötigen wir diese in diesem Beispiel nicht. Neben den Dialogelementen gibt es allerdings andere Klassen aus `java.awt`, die häufig auch in Swing-Programmen benötigt werden (nur eben in diesem einfachen Beispiel nicht), etwa die Layoutmanager, `Color`- oder `Font`-Objekte oder die Klasse `Graphics`.

Das Paket `java.awt.event` wird dagegen regelmäßig auch in Swing-Programmen benötigt, denn es enthält die Klassen für das Versenden von Events und Registrieren von Event-Handlern. Diese werden in Swing-Programmen in der gleichen Art und Weise benötigt wie in AWT-Programmen.

#### JFrame

Das Hauptfenster unserer Anwendung ist aus der Klasse `JFrame` abgeleitet, die ihrerseits aus `Frame` abgeleitet ist. `JFrame` ist eine der vier Klassen, mit denen in Swing Hauptfenster erzeugt werden können (`JDialog`, `JWindow` und `JApplet` sind die anderen drei). `JFrame` hat ähnliche Eigenschaften wie `Frame` und wird auch ähnlich programmiert wie diese. Beide unterscheiden sich jedoch in einem bedeutenden Punkt voneinander.

In Zeile 032 ist zu sehen, daß eine Komponente nicht einfach mit `add` auf dem Fenster plaziert wird. Statt dessen wird zunächst eine Methode `getContentPane` aufgerufen, und erst auf dem von ihr zurückgegebenen Container wird das Dialogelement mit `add` plaziert. Diese - auf den ersten Blick umständliche - Vorgehensweise ist allen Swing-Hauptfenstern gemein und wird durch deren innere Struktur verursacht. Der eigentliche Container mit den sichtbaren Dialogelementen (die ContentPane) ist nämlich Bestandteil einer ganzen Reihe geschachtelter Komponenten, in denen die übrigen Bestandteile des Fensters (etwa dessen Menü) untergebracht sind.

|  | Neben `add` darf auch die Methode `setLayout` nicht mehr direkt auf dem Hauptfenster aufgerufen werden. Analog zu `add` ist statt dessen `getContentPane().setLayout()` aufzurufen. Ein Verstoß gegen diese Regel löst in beiden Fällen eine Exception aus. |  |
Hinweis

#### JPanel

Die Buttonleiste und das Label mit seinem Textfeld werden im Beispielprogramm auf einem `JPanel` plaziert. `JPanel` ist das Swing-Pendant zu `Panel` und dient wie dieses dazu, eine Reihe von Dialogelementen unter Kontrolle eines eigenen Layoutmanagers anzuordnen. Anders als bei den Hauptfenstern gibt es hier keine ContentPane, sondern die Dialogelemente und der Layoutmanager werden dem Panel direkt zugewiesen. Die Bedienung eines `JPanel` entspricht fast vollständig der eines `Panel`.

|  | Die Vaterklasse von `JPanel` ist `JComponent`. Sie wird - mit Ausnahme der Hauptfenster - als Basisklasse für praktisch alle Swing-Komponenten verwendet. `JComponent` ist direkt aus `Container` abgeleitet und besitzt daher alle Eigenschaften der Klassen `Component` und `Container`. Die technische Unterscheidung zwischen Dialogelementen mit bzw. ohne Unterelemente wurde damit in Swing fallengelassen. Dennoch ist ein Button im praktischen Sinne natürlich nach wie vor ein elementares Dialogelement, und es gibt keine sinnvolle Möglichkeit, weitere Dialogelemente darauf zu plazieren. |  |
Hinweis

#### JLabel

Ein `JLabel` ist ein Dialogelement zur Anzeige eines (meist unveränderlichen) Textes. Es wird im Beispielprogramm verwendet, um das Textfeld im oberen Teil des Fensters zu beschriften. Im Gegensatz zu einem `Label` kann ein `JLabel` zusätzlich ein Icon enthalten. Im Beispielprogramm wird es in Zeile 024 direkt an den Konstruktor der Klasse übergeben. Auf diese Weise ist es sehr einfach möglich, zusätzliche grafische Elemente in Swing-Dialogen zu plazieren.

#### JTextField

Ein `JTextField` repräsentiert ein einzeiliges Eingabefeld für Textdaten. Für einfache Anwendungsfälle entspricht seine Bedienung der Klasse `TextField`. Unser Beispiel verwendet es zur Eingabe eines Namens. Zur verdeckten Eingabe von Paßwörtern eignet sich die aus `JTextField` abgeleitete Klasse `JPasswordField`. Sie entspricht einem `TextField` nach Aufruf von `setEchoCharacter`.

#### Tooltips und Umrandungen

Einige der Dialogelemente im Beispielprogramm enthalten einen Tooltip-Text. Dieser wird angezeigt, wenn die Maus über das Dialogelement bewegt und dort gehalten wird. Ein Tooltip sollte zusätzliche Informationen geben, die dem unerfahrenen Anwender eine Hilfe bei der Bedienung des Programms sind. Tooltips werden mit der Methode `setToolTipText` definiert, die alle aus `JComponent` abgeleiteten Komponenten besitzen.

Eine andere Fähigkeit, die ebenfalls bereits in der Klasse `JComponent` realisiert wurde, besteht darin, beliebigen Komponenten eine Umrandung zuweisen zu können. Das Beispielprogramm versieht seine beiden Panels mit einem eingelassenen Rahmen (Zeile 031 und Zeile 051). Dazu ist lediglich ein Aufruf der Methode `setBorder` mit Übergabe einer Instanz der Klasse `Border` erforderlich. Diese wird meist mit Hilfe einer der `create`-Methoden der Klasse `BorderFactory` erzeugt.

#### JList und JScrollPane

Eine `JList` ist eine Liste von Werten, von denen einer oder mehrere ausgewählt werden können. Ihre Bedienung ähnelt der aus dem AWT bekannten Klasse `List`; ihre Fähigkeiten gehen aber über diese hinaus. `JList` ist ein gutes Beispiel für die Aufteilung der Swing-Komponenten in Benutzerschnittstelle und Model. Anstatt - wie in unserem Beispiel - einfach ein Array von festen Werten an den Konstruktor zu übergeben, können mit Hilfe eines Listenmodells (repräsentiert durch eine Instanz der Klasse `ListModel`) sehr komplexe und dynamische Datenstrukturen in der Liste präsentiert werden. Auch die Benutzeroberfläche ist veränderbar. Mit Hilfe eigener "Renderer" können neben einfachen Texten beispielsweise auch Grafiken oder andere Objekte angezeigt werden.

In Zeile 036 kann man noch eine Besonderheit sehen. Eine `JList` bietet standardmäßig keine Möglichkeit zum Scrollen ihres Inhalts. Wird sie ohne weitere Maßnahmen auf dem Panel plaziert, können nur Elemente aus dem sichtbaren Bereich ausgewählt werden. Dieses Eigenschaft teilt sie mit anderen komplexen Swing-Elementen. Glücklicherweise gibt es eine einfache Lösung für dieses Problem. Die Liste ist nämlich lediglich in eine `JScrollPane` einzubetten, die an ihrer Stelle auf dem Dialog plaziert wird. Dieses vielseitige Dialogelement versieht Dialogelemente, die mehr Platz benötigen, als auf dem Bildschirm zur Verfügung steht, mit Schiebereglern und kümmert sich um alle Details des Scrollens der Daten.

#### JButton

Als letztes Dialogelement in unserem Beispiel wird die Klasse `JButton` verwendet. Sie dient zur Darstellung von Schaltflächen und erbt die meisten Eigenschaften aus ihrer Vaterklasse `AbstractButton` (die ihre Eigenschaften übrigens auch an Menüeinträge vererbt). Wie im Programm zu sehen, entsprechen die Grundlagen der Bedienung von `JButton` denen der Klasse `Button`.

#### Umschalten des Look-and-Feel

Wie in Abschnitt 35.1.2 erwähnt, kann das Look-and-Feel von Swing-Programmen zur Laufzeit umgeschaltet werden. Im Beispielprogramm ist das ab Zeile 061 zu sehen. Abhängig davon, welcher Button gedrückt wurde, wird der Variablen `plaf` der Klassenname einer Look-and-Feel-Implementierung zugewiesen. Durch Aufruf der Methode `setLookAndFeel` wird der `UIManager` angewiesen, das Look-and-Feel umzuschalten. Damit die Änderungen auch bei bereits auf dem Bildschirm befindlichen Dialogelementen sichtbar werden, wird anschließend durch Aufruf von `updateComponentTreeUI` der Klasse `SwingUtilities` der gesamte Dialog neu dargestellt.

|  | Schlägt der Aufruf von `setLookAndFeel` fehl (was je nach Plattform durchaus passieren kann), löst die Methode eine Ausnahme des Typs `UnsupportedLookAndFeelException` oder eine der Instanzierungsausnahmen aus. Das Programm sollte diese Ausnahme abfangen, das bestehende Look-and-Feel aktiviert lassen und den Anwender darüber in Kenntnis setzen. |  |
Hinweis

Titel | Inhalt | Suchen | Index | DOC | Handbuch der Java-Programmierung, 3. Auflage, Addison Wesley, Version 3.0
<< | < | > | >> | API | © 1998-2002 Guido Krüger, http://www.javabuch.de