Titel   Inhalt   Suchen   Index   API  Go To Java 2, Zweite Auflage, Handbuch der Java-Programmierung
 <<    <     >    >>  Kapitel 36 - Swing: Container und Menüs

36.1 Hauptfenster



36.1.1 JFrame

Die Klasse JFrame ist die wichtigste Hauptfensterklasse in Swing. Sie ist aus java.awt.Frame abgeleitet und stellt ein Hauptfenster mit Rahmen, Systemmenü und Standardschaltflächen zur Verfügung. Ein JFrame kann ebenso einfach instanziert werden wie ein Frame:

public JFrame()
public JFrame(String title)
javax.swing.JFrame

Der parameterlose Konstruktor erzeugt ein Hauptfenster mit einer leeren Titelzeile, der andere schreibt den übergebenen String hinein. Da JFrame aus Frame abgeleitet ist, stehen alle Methoden aus Window, Container und Component zur Verfügung. Ein einfaches Beispielprogramm mit einem leeren Hauptfenster, das sich über den Schließen-Button beenden läßt, können wir (analog zu den Beispielen in Kapitel 31) wie folgt realisieren:

001 /* Listing3601.java */
002 
003 import javax.swing.*;
004 import java.awt.event.*;
005 
006 public class Listing3601
007 extends JFrame
008 {
009   public Listing3601()
010   {
011     super("Ein einfacher JFrame");
012     addWindowListener(new WindowClosingAdapter(true));
013   }
014 
015   public static void main(String[] args)
016   {
017     Listing3601 wnd = new Listing3601();
018     wnd.setLocation(100, 100);
019     wnd.setSize(300, 200);
020     wnd.setVisible(true);
021   }
022 }
Listing3601.java
Listing 36.1: Verwendung der Klasse JFrame

Das Programm erzeugt ein Hauptfenster der Größe 300 * 200 an der Bildschirmposition (100, 100). In der Titelzeile steht "Ein einfacher JFrame", und das Programm läßt sich durch einen Klick auf den Schließen-Button beenden:

Abbildung 36.1: Ein einfaches JFrame-Beispiel

RootPane, LayeredPane und ContentPane

Ein bedeutender Unterschied zwischen den AWT- und Swing-Hauptfenstern besteht in ihrer Komponentenstruktur und den sich daraus ergebenden Unterschieden in der Bedienung. Während die Komponenten eines AWT-Fensters direkt auf dem Fenster plaziert werden, besitzt ein Swing-Hauptfenster eine einzige Hauptkomponente, die alle anderen Komponenten aufnimmt.

Diese Hauptkomponente wird als RootPane bezeichnet und ist vom Typ JRootPane. Sie übernimmt die Rolle einer Art Verwaltungsinstanz für alle anderen Komponenten des Hauptfensters. Eine RootPane enthält folgende Komponenten:

Die LayeredPane enthält ihrerseits zwei Unterkomponenten:

Damit ergibt sich folgende Struktur:

Abbildung 36.2: Die Struktur einer RootPane

LayeredPane und GlassPane liegen "übereinander" und füllen das Fenster jeweils komplett aus. Die GlassPane ist normalerweise durchsichtig und wird meist nicht zur Grafikausgabe benutzt. Sie könnte dann verwendet werden, wenn Effekte erzielt werden sollen, die das Fenster als Ganzes betreffen (und nicht seine einzelnen Dialogelemente). Eine (beispielsweise von JInternalFrame genutzte) Funktion besteht darin, Mausereignisse abzufangen, bevor sie an andere Komponenten weitergegeben werden.

Die LayeredPane enthält das Menü und die Dialogelemente der Anwendung. Als Instanz der Klasse JLayeredPane verfügt sie über die Fähigkeit, Dialogelemente nicht nur neben-, sondern in kontrollierter Weise auch übereinander anzuordnen. Das ist beispielsweise wichtig, um Menüs oder interne Dialoge über den Komponenten anzuzeigen, die sie verdecken. Tatsächlich verdeckt das in der LayeredPane gehaltene Menü die in seiner ContentPane plazierten Dialogelemente der Anwendung.

Das hört sich alles sehr kompliziert an, und mancher wird sich fragen, ob soviel Aufwand wirklich nötig war. Glücklicherweise braucht eine Swing-Anwendung sich um die Details gar nicht zu kümmern. Einerseits wird die RootPane, und mit ihr die darin enthaltene GlassPane, LayeredPane und ContentPane, beim Anlegen des Fensters automatisch erzeugt (einzig die Menüleiste bleibt standardmäßig leer). Zweitens implementieren alle Hauptfenster das Interface RootPaneContainer, das den Zugriff auf die RootPane vereinfacht. Einige seiner Methoden sind:

public JRootPane getRootPane()
public Container getContentPane()
public JLayeredPane getLayeredPane()
public Component getGlassPane()
javax.swing.RootPaneContainer

Um auf einem Hauptfenster Komponenten zu plazieren, ist es also nicht nötig, zunächst mit getRootPane die RootPane, dann mit getLayeredPane die LayeredPane und schließlich mit getContentPane die ContentPane zu beschaffen, sondern es kann direkt getContentPane aufgerufen werden. Neben den getter-Methoden gibt es auch setter-Methoden, mit denen der strukturelle Aufbau der RootPane vollständig verändert werden kann. Darauf wollen wir aber nicht weiter eingehen.

Dialogelemente plazieren

Das Einfügen und Anordnen von Dialogelementen auf einem Hauptfenster erfolgt also über dessen ContentPane. Die Aufrufe von add und setLayout werden damit nicht direkt auf dem Fenster ausgeführt, sondern auf dessen ContentPane, die über einen Aufruf von getContentPane beschafft werden kann.

Um das zu demonstrieren, wollen wir das vorige Beispiel um drei Buttons erweitern, die mit Hilfe eines GridLayout der Größe 3 * 1 angeordnet werden:

001 /* Listing3602.java */
002 
003 import javax.swing.*;
004 import java.awt.*;
005 import java.awt.event.*;
006 
007 public class Listing3602
008 extends JFrame
009 {
010   public Listing3602()
011   {
012     super("Ein einfacher JFrame");
013     //WindowListener hinzufügen
014     addWindowListener(new WindowClosingAdapter(true));
015     //Layout setzen und Buttons hinzufügen
016     Container contentPane = getContentPane();
017     contentPane.setLayout(new GridLayout(3, 1));
018     contentPane.add(new JButton("Button 1"));
019     contentPane.add(new JButton("Button 2"));
020     contentPane.add(new JButton("Button 3"));
021   }
022 
023   public static void main(String[] args)
024   {
025     Listing3602 wnd = new Listing3602();
026     wnd.setLocation(100, 100);
027     wnd.setSize(300, 200);
028     wnd.setVisible(true);
029   }
030 }
Listing3602.java
Listing 36.2: Anordnen von Dialogelementen in einem Hauptfenster

Das Programm hat nun folgendes Aussehen:

Abbildung 36.3: Ein Hauptfenster mit Dialogelementen

Gerade am Anfang passiert es mitunter, daß add oder setLayout versehentlich direkt aus dem Hauptfenster aufgerufen werden. Um das zu verhindern, besitzen die Hauptfensterklassen einen Mechanismus, der in einem solchen Fall eine Ausnahme mit einem entsprechenden Warnhinweis auslöst. Dieser kann zwar mit der Methode setRootPaneCheckingEnabled deaktiviert werden, normalerweise ist das aber nicht zu empfehlen.

 Warnung 

36.1.2 JWindow

Die zweite Hauptfensterklasse, die wir in diesem Kapitel vorstellen, ist JWindow. Sie ist aus Window abgeleitet und dient wie diese dazu, ein rahmenloses Fenster zu erzeugen, das an beliebiger Stelle und in beliebiger Größe auf dem Bildschirm plaziert werden kann. JWindow besitzt drei Konstruktoren:

public JWindow()
public JWindow(Frame owner)
public JWindow(Window owner)
javax.swing.JWindow

Ebenso wie JFrame besitzt auch JWindow eine RootPane mit der im vorigen Abschnitt beschriebenen Struktur. Dialogelemente und Layoutmanager werden also nicht direkt auf dem Fenster, sondern auf der ContentPane plaziert. Zur einfacheren Verwendung implementiert auch JWindow das Interface RootPaneContainer.

Als Beispiel für die Anwendung von JWindow wollen wir einen einfachen SplashScreen konstruieren, also ein Fenster, das nach dem Start eines Programmes angezeigt wird und nach dessen Initialisierung wieder entfernt wird. Dazu leiten wir eine Klasse SplashScreen von JWindow ab und plazieren darin ein Icon und einen Text. Der Name der Icondatei und der Text können an den Konstruktor übergeben werden. Das Programm soll jeweils ein Drittel der verfügbaren Höhe und Breite des Bildschirms belegen und das Icon und den Text zentriert darin anzeigen.

001 /* SplashScreen.java */
002 
003 import javax.swing.*;
004 import javax.swing.border.*;
005 import java.awt.*;
006 import java.awt.event.*;
007 
008 public class SplashScreen
009 extends JWindow
010 {
011   public SplashScreen(String image, String text)
012   {
013     JPanel contentPane = new JPanel(); 
014     contentPane.setLayout(new BorderLayout());
015     Border bd1 = BorderFactory.createBevelBorder( 
016       BevelBorder.RAISED
017     );
018     Border bd2 = BorderFactory.createEtchedBorder();
019     Border bd3 = BorderFactory.createCompoundBorder(bd1, bd2);
020     ((JPanel)contentPane).setBorder(bd3);
021     ImageIcon icon = new ImageIcon(image);
022     contentPane.add("North",  new JLabel(" ", JLabel.CENTER));
023     contentPane.add("Center", new JLabel(icon, JLabel.CENTER));
024     contentPane.add("South",  new JLabel(text, JLabel.CENTER));
025     setContentPane(contentPane); 
026   }
027 
028   public void showFor(int millis)
029   {
030     Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
031     setLocation(dim.width / 3, dim.height / 3);
032     setSize(dim.width / 3, dim.height / 3);
033     setVisible(true);
034     try {
035       Thread.sleep(millis);
036     } catch (InterruptedException e) {
037     }
038     setVisible(false);
039   }
040 
041   public static void main(String[] args)
042   {
043     SplashScreen intro = new SplashScreen(
044       "mine.gif", 
045       "(C) Copyright 2000, J. Krüger, All Rights Reserved"
046     );
047     intro.showFor(3000);
048     System.exit(0);
049   }
050 }
SplashScreen.java
Listing 36.3: Ein einfacher SplashScreen

Die Ausgabe des Programms sieht so aus:

Abbildung 36.4: Ein einfacher SplashScreen

Das Programm ist prinzipiell so aufgebaut wie die bisherigen Swing-Beispiele, zeigt aber bei näherem Hinsehen einige Besonderheiten. Zunächst definiert es einen eigenen ContentPane. In Zeile 013 wird dazu ein JPanel instanziert und mit einem BorderLayout versehen (der Standard-Layoutmanager von JPanel ist FlowLayout). Alle Dialogelemente werden auf diesem Panel plaziert. In Zeile 025 wird das Panel durch Aufruf von setContentPane als ContentPane des Fensters definiert.

Zum anderen zeigt das Programm ein paar zusätzliche Möglichkeiten, Umrandungen zu verwenden. Ab Zeile 015 werden mit Hilfe der Methoden createBevelBorder und createEtchedBorder der Klasse BorderFactory zwei unabhängige Umrandungen konstruiert. Durch Aufruf von createCompoundBorder werden sie zu einer neuen Umrandung zusammengefaßt und anschließend an den ContentPane übergeben.

36.1.3 JDialog

Neben einem oder mehreren langlebigen Hauptfenstern besitzt eine Anwendung meist auch Dialogfenster. Sie werden oft nur vorübergehend aufgerufen, um eine temporäre Kommunikation zwischen Anwender und Programm zu etablieren. Dialogfenster unterscheiden sich meist dadurch von Hauptfenstern, daß sie kein Menü und nur eingeschränkte Systemfunktionen besitzen. Zudem ist ihre Größe oft nicht veränderbar, und sie halten (als modale Fenster) während der eigenen Ausführung den Programmfluß im übrigen Programm an.

Mit der aus Dialog abgeleiteten Klasse JDialog stehen auch in Swing Dialogfenster zur Verfügung. Sie besitzen denselben strukturellen Aufbau wie JFrame und JWindow und implementieren ebenfalls das Interface RootPaneContainer. Auch hier erfolgt also das Hinzufügen und Anordnen von Komponenten nicht auf dem Fenster selbst, sondern auf seiner ContentPane. JDialog besitzt eine Vielzahl von Konstruktoren. Die wichtigsten sind:

public JDialog(Frame owner)
public JDialog(Frame owner, boolean modal)
public JDialog(Frame owner, String title)
public JDialog(Frame owner, String title, boolean modal)
javax.swing.JDialog

Als owner sollte der Aufrufer dabei das Fenster übergeben, zu dem der Dialog logisch gehört. Alle Konstruktoren gibt es auch in einer Form, bei der der owner vom Typ Dialog ist. Wahlweise kann ein JDialog auch ohne owner konstruiert werden (mit dem parameterlosen Konstruktor), doch dann kann es unter Umständen Fokusprobleme beim Wechsel zwischen mehreren Anwendungen geben.

Die übrigen Parameter geben den Titel des Dialogs an und legen fest, ob er modal oder nicht-modal sein soll. Bei einem modalen Dialog wird der Aufruf von show (bzw. setVisible(true)) erst dann beendet, wenn der Dialog geschlossen wurde. Bei einem nicht-modalen Dialog fährt das Programm dagegen unmittelbar mit der nächsten Anweisung hinter show fort.

36.1.4 JOptionPane

Eine weitere (und noch dazu sehr bequeme) Möglichkeit, Swing-Dialoge zu erzeugen, steht mit der Klasse JOptionPane zur Verfügung. Diese ist in der Lage, einfache Dialoge, die lediglich ein Icon und einen Text oder ein Eingabefeld und eine Auswahl der Buttons "Yes", "No" und "Cancel" enthalten, mit einem einzigen Aufruf einer statischen Methode zu erzeugen. JOptionPane ist sehr vielseitig, wir wollen uns an dieser Stelle allerdings auf ihre wichtigsten Anwendungen beschränken.

Anzeigen einer Nachricht

In seiner einfachsten Form kann JOptionPane dazu verwendet werden, ein Dialogfenster mit Titel, Icon und Hinweistext anzuzeigen, das mit Hilfe eines "OK"-Buttons beendet werden kann. Dazu stehen verschiedene Varianten der Methode showMessageDialog zur Verfügung:

public static void showMessageDialog(
  Component parentComponent,
  Object message
)

public static void showMessageDialog(
  Component parentComponent,
  Object message,
  String title,
  int messageType
)

public static void showMessageDialog(
  Component parentComponent,
  Object message,
  String title,
  int messageType,
  Icon icon
)
javax.swing.JOptionPane

Aufrufe von showMessageDialog sind grundsätzlich modal. Erst wenn der Dialog vom Anwender beendet wurde, wird die nächste Anweisung ausgeführt. Der Parameter parentComponent bezeichnet die Vaterkomponente, aus der heraus der Dialog aufgerufen wurde, und message ist der anzuzeigende Text. Soll eine eigene Titelzeile angegeben werden, kann dazu title verwendet werden, andernfalls wird "Message" angezeigt. Wahlweise kann mit dem Parameter icon ein Icon angegeben werden, das neben dem Text angezeigt wird. Alternativ kann auch durch Übergabe einer der Konstanten ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE oder PLAIN_MESSAGE an den Parameter messageType ein Standard-Icon erzeugt werden:

Abbildung 36.5: Die Standard-Icons bei JOptionPane

Eingabe einer Bestätigung

Mit den verschiedenen Varianten der Methode showConfirmDialog kann ein Dialog erzeugt werden, der neben den zuvor besprochenen Fähigkeiten die Möglichkeit bietet, die Auswahl der Buttons zu beeinflussen, mit denen der Dialog beendet werden kann.

public static int showConfirmDialog(
  Component parentComponent,
  Object message
)

public static int showConfirmDialog(
  Component parentComponent,
  Object message,
  String title,
  int optionType
)

public static int showConfirmDialog(
  Component parentComponent,
  Object message,
  String title,
  int optionType,
  int messageType
)

public static int showConfirmDialog(
  Component parentComponent,
  Object message,
  String title,
  int optionType,
  int messageType,
  Icon icon
)
javax.swing.JOptionPane

Die Parameter entsprechen im wesentlichen denen der Methode showMessageDialog. Zusätzlich kann mit optionType eine der Konstanten YES_NO_OPTION, OK_CANCEL_OPTION oder YES_NO_CANCEL_OPTION angegeben werden, um zu entscheiden, welche Kombination von Buttons der Dialog anzeigen soll:

Abbildung 36.6: Button-Kombinationen bei showConfirmDialog

showConfirmDialog ist ebenfalls modal und ihr Rückgabewert zeigt an, auf welche Weise der Dialog beendet wurde:

Rückgabewert Bedeutung
YES_OPTION Mit dem "Yes"-Button
NO_OPTION Mit dem "No"-Button
CANCEL_OPTION Mit dem "Cancel"-Button
OK_OPTION Mit dem "OK"-Button
CLOSED_OPTION Mit dem "Schließen"-Button der Titelzeile

Tabelle 36.1: Rückgabewerte von showConfirmDialog

Eingabe von Daten

Mit der Möglichkeit, neben dem Icon und dem Nachrichtentext auch ein Textfeld im Dialog zu plazieren, kann JOptionPane auch zur Erfassung einfacher Daten verwendet werden. Die dazu aufzurufende Methode showInputDialog gibt es ebenfalls in mehreren Varianten:

public static String showInputDialog(
  Component parentComponent,
  Object message
)

public static String showInputDialog(
  Component parentComponent,
  Object message,
  String title,
  int messageType
)

public static Object showInputDialog(
  Component parentComponent,
  Object message,
  String title,
  int messageType,
  Icon icon,
  Object[] selectionValues,
  Object initialSelectionValue
)
javax.swing.JOptionPane

In der einfachsten Form werden lediglich ein Dialog mit dem Titel "Input", die angegebene Nachricht mit einem Icon und das Textfeld zur Eingabe der Daten angezeigt. Die zweite Variante erlaubt zusätzlich die Angabe der Titelzeile und die Auswahl des Icontyps. In der letzten Variante wird anstelle des Textfelds eine Combobox zur Dateneingabe verwendet. Der Parameter selectionValues gibt die in der Combobox anzuzeigenden Elemente an (sie werden mit toString in Strings konvertiert), und initialSelectionValue gibt an, welches von ihnen standardmäßig selektiert werden soll.

Bei allen Methoden ist der Rückgabewert ein String mit den vom Anwender eingegebenen Daten. Falls eine Combobox zur Auswahl verwendet wurde, wird der String-Wert des ausgewählten Elements zurückgegeben. Ein Rückgabewert von null zeigt an, daß der Anwender den Dialog abgebrochen hat.

Das folgende Programm zeigt eine einfache Anwendung von JOptionPane, bei der der Anwender einen Wert aus einer vordefinierten Liste auswählen kann:

001 /* Listing3604.java */
002 
003 import javax.swing.*;
004 import java.awt.*;
005 import java.awt.event.*;
006 
007 public class Listing3604
008 extends JFrame
009 {
010   private static final String[] QUARTALE = {
011     "1. Quartal", "2. Quartal", "3. Quartal", "4. Quartal"
012   };
013 
014   public Listing3604()
015   {
016     super("Test von JOptionPane");
017     addWindowListener(new WindowClosingAdapter());
018   }
019 
020   public static void main(String[] args)
021   {
022     Listing3604 wnd = new Listing3604();
023     wnd.setLocation(100, 100);
024     wnd.setSize(300, 200);
025     wnd.setVisible(true);
026     String ret = (String)JOptionPane.showInputDialog(
027       wnd,
028       "Wählen Sie das Quartal aus",
029       "JOptionPane.showInputDialog",
030       JOptionPane.QUESTION_MESSAGE,
031       null,
032       QUARTALE,
033       QUARTALE[2]
034     );
035     System.out.println("Ausgewählt wurde " + ret);
036   }
037 }
Listing3604.java
Listing 36.4: Anwendungsbeispiel für JOptionPane

Der vom Programm erzeugte Dialog sieht unmittelbar nach dem Aufruf von showInputDialog so aus:

Abbildung 36.7: Die Methode showInputDialog

36.1.5 JApplet

Die Klasse JApplet ist eine einfache Erweiterung von java.applet.Applet. Sie dient zur Entwicklung von Applets, die Swing-Dialogelemente zur Gestaltung der Oberfläche verwenden. Die Unterschiede zwischen beiden Klassen sind nicht sehr umfangreich; insbesondere werden die Methoden init, start, stop und destroy in derselben Weise verwendet wie bei der Klasse Applet.

Wie bei den anderen Hauptfenstern ist auch hier der wichtigste Unterschied, daß JApplet die in Abschnitt 36.1.1 beschriebene RootPane-Struktur realisiert. Die Klasse implementiert ebenfalls das RootPaneContainer-Interface, und alle Komponenten müssen an die ContentPane übergeben werden. Da die Applet-Programmierung ab Kapitel 39 ausführlich beschrieben wird, wollen wir uns an dieser Stelle auf ein einfaches Beispiel beschränken:

001 /* JAppletTest.java */
002 
003 import javax.swing.*;
004 import java.awt.*;
005 import java.awt.event.*;
006 
007 public class JAppletTest
008 extends JApplet
009 {
010   public void init()
011   {
012     Container contentPane = getContentPane();
013     contentPane.setLayout(new GridLayout(3, 1));
014     contentPane.add(new JButton("Button 1"));
015     contentPane.add(new JButton("Button 2"));
016     contentPane.add(new JButton("Button 3"));
017   }
018 }
JAppletTest.java
Listing 36.5: Anwendungsbeispiel für JApplet

Das Programm stellt ein sehr einfaches Applet dar, das - analog zu Listing 36.2 - drei Buttons in einem GridLayout anzeigt. Es kann wie folgt in eine HTML-Datei eingebettet werden:

001 <html>
002 <head><title>JAppletTest</title></head>
003 
004 <body>
005 <h1>JAppletTest</h1>
006 
007 <applet code="JAppletTest.class" width=300 height=200>
008 Hier steht das JAppletTest
009 </applet>
010 
011 </body>
012 </html>
japplet.html
Listing 36.6: HTML-Datei für JApplet-Beispiel

Das Applet kann nun mit Hilfe des AppletViewers gestartet werden:

appletviewer japplet.html

36.1.6 JInternalFrame

Bei vielen Programmen ist es üblich, daß sie ein einziges Hauptfenster besitzen und ihre zahlreichen, gleichzeitig geöffneten Kindfenster innerhalb dieses Hauptfensters anordnen. Diese unter Windows als MDI (Multiple Document Interface) bezeichnete Technik ist bei bestimmten Typen von Anwendungen mittlerweile weitverbreitet (z.B. bei Textverarbeitungen, Grafikprogrammen oder Entwicklungsumgebungen).

Während im AWT keine Möglichkeit vorgesehen war, MDI-Anwendungen zu entwickeln, ist es in Swing recht einfach. Dazu werden lediglich zwei Arten von Komponenten benötigt:

Der Desktop

Als Desktop ist prinzipiell jede beliebige Hauptfensterklasse geeignet, meist wird aber die Klasse JFrame verwendet. Um die Kindfenster zu verwalten, wird die vordefinierte ContentPane durch eine Instanz der Klasse JDesktopPane ersetzt. Diese von JLayeredPane abgeleitete Klasse besitzt einen DesktopManager, der für die Verwaltung der Kindfenster zuständig ist. Der DesktopManager wird beispielsweise benachrichtigt (und führt alle dazu erforderlichen Aktionen aus), wenn ein Kindfenster verkleinert, vergrößert oder verschoben werden soll.

DesktopManager ist ein Interface, das eine Vielzahl von Methoden enthält. Mit der Klasse DefaultDesktopManager gibt es eine Standardimplementierung, die für viele Zwecke ausreichend ist.

 Hinweis 

Die Kindfenster

Die Kindfenster werden aus JInternalFrame abgeleitet; einem Dialogelement, das recht überzeugend vortäuscht, ein Hauptfenster zu sein. Tatsächlich ist JInternalFrame direkt aus JComponent abgeleitet und nicht aus JFrame, wie man es vielleicht vermuten könnte. Der Grund liegt darin, daß JFrame als Frame stets eine betriebssystemspezifische Fensterressource besitzt und damit für die Verwendung innerhalb der Grenzen eines anderen Fensters ungeeignet ist.

Eine betriebssystemspezifische Ressource für MDI-Kindfenster steht aber nicht auf allen grafischen Oberflächen zur Verfügung, und so haben sich die Swing-Entwickler entschlossen, JInternalFrame als leichtgewichtige Komponente selbst zu realisieren.

Das hat einige Konsequenzen:

Um die Kindfenster zu aktivieren, müssen sie durch Aufruf von setVisible sichtbar gemacht und mit add auf dem Desktop plaziert werden. Bis zum JDK 1.2 war der Aufruf von setVisible nicht unbedingt erforderlich, denn ein JInternalFrame war standardmäßig sichtbar. Zur Angleichung an die anderen Hauptfensterklassen wurde dies mit dem JDK 1.3 geändert.

 JDK1.1-1.3 

JInternalFrame besitzt diverse Konstruktoren. Das nachfolgende Syntaxdiagramm zeigt nur den umfangreichsten von ihnen. Alle anderen ergeben sich, indem man auf der rechten Seite nicht benötigte Argumente wegfallen läßt:

public JInternalFrame(
  String title,
  boolean resizable,
  boolean closable,
  boolean maximizable,
  boolean iconifiable
)
javax.Swing.JInternalFrame

JInternalFrame implementiert das schon erläuterte Interface RootPaneContainer und stellt zusätzlich verschiedene Methoden zur Verfügung. Einige von ihnen sind:

public void setClosable(boolean b)
public void setResizable(boolean b)
public void setIconifiable(boolean b)
public void setMaximizable(boolean b)

public void setTitle(String title)

public void setDefaultCloseOperation(int operation)
javax.Swing.JInternalFrame

setClosable entscheidet, ob das Fenster geschlossen, und setResizable, ob seine Größe verändert werden kann. setIconifiable legt fest, ob das Fenster in ein Symbol verkleinert, und setMaximizable, ob es maximiert werden kann. Mit setTitle kann der Rahmentitel angegeben werden, und mit setDefaultCloseOperation wird angegeben, wie das Fenster sich beim Schließen verhalten soll. Hier kann eine der Konstanten DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE oder DISPOSE_ON_CLOSE angegeben werden.

Beispielprogramm

Nach diesen Vorbemerkungen wollen wir ein einfaches Beispielprogramm erstellen. Es soll einen JFrame als Desktop mit zwei Kindfenstern enthalten. Diese sollen alle Standardbedienelemente enthalten, vergrößer- und verkleinerbar sein und innerhalb des Desktops verschoben werden können.

Wir erstellen dazu eine Klasse DesktopFrame, die mit einem DefaultDesktopManager ein Desktop aufbaut. Mit ihrer Methode addChild kann ein Kindfenster an einer bestimmten Position auf dem Desktop plaziert werden. Weiterhin definieren wir eine aus JInternalFrame abgeleitete Klasse ChildFrame. Sie legt im Konstruktor die Eigenschaften des Fensters fest, hat darüber hinaus aber keine Funktionalitäten.

001 /* Listing3607.java */
002 
003 import java.awt.*;
004 import java.awt.event.*;
005 import javax.swing.*;
006 
007 class DesktopFrame
008 extends JFrame
009 {
010   private JDesktopPane desk;
011 
012   public DesktopFrame()
013   {
014     super("DesktopFrame");
015     this.desk = new JDesktopPane();
016     desk.setDesktopManager(new DefaultDesktopManager());
017     setContentPane(desk);
018     addWindowListener(new WindowClosingAdapter());
019   }
020 
021   public void addChild(JInternalFrame child, int x, int y)
022   {
023     child.setLocation(x, y);
024     child.setSize(200, 150);
025     child.setDefaultCloseOperation(
026       JInternalFrame.DISPOSE_ON_CLOSE
027     );
028     desk.add(child);
029     child.setVisible(true);
030   }
031 }
032 
033 class ChildFrame
034 extends JInternalFrame
035 {
036   public ChildFrame(String title)
037   {
038     super("Child " + title, true, true);
039     setIconifiable(true);
040     setMaximizable(true);
041     setBackground(Color.lightGray);
042   }
043 }
044 
045 public class Listing3607
046 {
047   public static void main(String[] args)
048   {
049     //Desktop erzeugen
050     DesktopFrame desktop = new DesktopFrame();
051     desktop.setLocation(100, 100);
052     desktop.setSize(400, 300);
053     desktop.setVisible(true);
054     //Zwei ChildFrames hinzufügen
055     desktop.addChild(new ChildFrame("1"), 10, 10);
056     desktop.addChild(new ChildFrame("2"), 20, 20);
057   }
058 }
Listing3607.java
Listing 36.7: Die Klasse JInternalFrame

Die Ausgabe des Programms sieht so aus:

Abbildung 36.8: Die Klasse JInternalFrame


 Titel   Inhalt   Suchen   Index   API  Go To Java 2, Zweite Auflage, Addison Wesley, Version 2.0
 <<    <     >    >>  © 2000 Guido Krüger, http://www.gkrueger.com