Java Standard: Grafische Oberflächen mit Swing: Top Level Container


Top-Level Container - Hauptträger grafischer Komponenten

Bearbeiten

Zur Aufnahme von grafischen Komponenten stellt die Java Swing API so gennante Container zur Verfügung. Container ist ein Abstract Window Toolkit (AWT), das andere AWT Komponenten aufnehmen kann. Die Klasse Container steht seit JDK 1.0 zur Verfügung und erbt von der Klasse Component.

In der Swing API gibt es so genannte Top-Level Container für verschiedene Zwecke. Der Begriff Top-Level Container soll ausdrücken, dass sie in der Hierarchie einer GUI ganz oben stehen. Jede GUI Komponente muss einer solchen Hierarchie angehören.

 

In Anlehnung an die Java Tutorials http://java.sun.com/docs/books/tutorial/uiswing/components/toplevel.html

Jeder Top-Level Container hält also eine Hierarchie, dessen Wurzel (Root) er selbst darstellt. Um leichtgewichtige grafische Swing-Komponenten nutzen zu können, müssen diese zu einer solchen Hierarchie hinzugefügt werden. Man muss also zunächst einen Top-Level Container als Basis erstellen und kann diesem dann Swing-Komponenten hinzufügen.

Die gelb markierten Klassen sind hauptsächlich als interne Verwaltungsklassen der Top-Level Container zu sehen und sollten nur angefasst werden, wenn es sich nicht vermeiden lässt. Beispielsweise muss man die Schichtung der unterschiedlichen Elemente nicht festlegen, weil dies bereits von JLayeredPane übernommen wird. Popups bzw. Dialoge, die zum Top-Level Container gehören werden beispielsweise automatisch in den Vordergrund gelegt und zum Verdecken von Elementen kann das Glass Pane verwendet werden. Wenn Sie alle Komponenten in der richtigen Reihenfolge hinneinladen, sollten Sie also nicht auf diese Klasse zugreifen müssen.

Die Swing API bietet verschiedene Klassen als Top-Level Container für verschiedene Aufgaben an.

JFrame
Top-Level Container für Applikationen. Jede Applikation, die eine mit Swing erstellte GUI nutzt, benötigt einen JFrame als Top-Level Container.
JApplet
Applet, das Swing Komponenten nutzen kann. Applets sind spezielle Java Programme, die von Java-fähigen Browsern heruntergeladen und ausgeführt werden können.
JDialog
Top-Level Container für Dialoge.

Das Root Pane

Bearbeiten

Jeder Top-Level Container in Swing basiert auf einem Root Pane. Dabei wird dieses Objekt automatisch für jeden Top-Level Container erzeugt. Dieses Root Pane organisiert die Komponenten, die einen Top-Level Container ausmachen:

Layered Pane (JLayeredPane)
Dient der Organisation der einzelnen Schichten bzw. Komponenten eines Fensters auf der Z-Achse. Sprich, welche Komponenten werden im Vorder- und welche im Hintergrund angezeigt, welche Komponenten werden von anderen überlappt usw. Letztendlich hat jedoch der Layout Manager des Content Panes das Sagen bezüglich Größe und Position von Komponenten.
Content Pane (keine eigenständige Klasse - Container)
Container, der die Liste der hinzugefügten Komponenten hält.
Glass Pane (keine eigenständige Klasse - JPanel)
Kann als oberste Schicht Nutzeraktionen abfangen und Bilder über die unter ihm befindlichen Schichten legen.
Menu Bar (JMenuBar)
Eine Menüleiste kann optional angebracht werden. Diese kann dann Menüs aufnehmen.

Hinzufügen von Komponenten

Bearbeiten

Die Hierarchie eines Containers wird über eine Liste realisiert, in der alle hinzugefügten Komponenten gespeichert werden.Fügt man eine Komponente hinzu, ohne den Index festzulegen, an den sie gespeichert werden soll, wird sie einfach an das Ende der Liste gesetzt. Damit verdeckt sie die anderen Komponenten, sofern es zu layoutbedingten Überschneidungen kommt. Der Nutzer einer Software sitzt also entgegen der Implikation, die der Begriff Top-Level mitbringt am entgegengesetzten Ende der Hierarchie.

Einem Top-Level Container können alle Objekte von Typ Component hinzugefügt werden. Die Vorgehensweise zum Hinzufügen, sollte folgendermaßen aussehen:

        ...
	eintopLevelContainer.getContentPane().add(eineComponent);
	...

Ein Top-Level Container verwendet standardmäßig ein BorderLayout als Layout Manager. Um dies zu ändern, kann man einem JPanel einen anderen Layout Manager zuweisen und das Content Pane durch dieses neue JPanel ersetzen:

	...
	JPanel contentPane = new JPanel(new FlowLayout());	
	contentPane.add(eineComponent);
	contentPane.add(andereComponent);

	topLevelContainer.setContentPane(contentPane);
	...

Es gibt andere Möglichkeiten, die jedoch nicht zu empfehlen sind, da Sie laut Java Tutorial nicht so "sauber" sind wie die oben vorgestellte.

Zu beachten
Eine Komponente kann immer nur zu einem Container gehören. Wenn man eine Komponente, die bereits einem Container zugehörig ist einem anderen Container hinzufügt, wird sie aus dem aktuellen Container entfernt und dann an die Hierarchie des neuen angeknüpft.

Ein Beispiel

Bearbeiten

Programmierung eines Fensters mit drei Buttons, die in einer Reihe angeordnet sind. Das jeweilige Ziel einer Anweisung kann den Kommentaren entnommen werden.

 

import javax.swing.*;

public class ButtonFrame {

    private static void createAndShowGUI() {
        // Fenster mit Titel erstellen
        JFrame frame = new JFrame("ButtonFrame");

	// Ändern des Fensterverhaltens bei Klick auf Schließen-Button
	// Standardoperation waere verstecken des Fensters
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

	// Erstellen eines neuen JPanels, das als Standard den 
	// FlowLayout Manager verwendet
	JPanel contentPanel = new JPanel(new FlowLayout());
	// JPanel als Content Pane festlegen
	frame.setContentPane(contentPanel);
	
	// Buttons erzeugen und zum Content Pane hinzufügen
	JButton okButton = new JButton("OK");
	JButton cancelButton = new JButton("Cancel");
	JButton blaButton = new JButton("Bla");
        frame.getContentPane().add(okButton);
	frame.getContentPane().add(cancelButton);
	frame.getContentPane().add(blaButton);

        //Fenster anzeigen
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        // Aufgrund von Thread-Sicherheit sollte die Methode vom 
	// event-dispatching Thread aufgerufen werden
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

Würde man hingegen den Layout Manager nicht auf ein FlowLayout setzen, erhielte man folgendes Bild.

 

Da das BorderLayout eine Angabe der Position (mittig, oben, unten, links oder rechts) relativ zur Mitte des Fensters erwartet und diese Angabe nicht gemacht wird, legt es die Buttons einfach übereinander.

Beheben lässt sich dies, indem man der add() Methode eine Position mitgibt.

...
    frame.getContentPane().add(okButton, BorderLayout.LINE_START);
    frame.getContentPane().add(cancelButton, BorderLayout.CENTER);
    frame.getContentPane().add(blaButton, BorderLayout.LINE_END);
...

 

Jedoch füllen die Buttons im Gegensatz zum FlowLayout nun die gesamte Höhe des Fensters aus.

Weiterführende Inhalte

Bearbeiten
LayoutManager - Wie bestimmen Sie die Anordnung von Komponenten in einem Container?
JPanel - Wie können Sie Komponenten gruppieren, organisieren?