Wie richtet man ein GridBagLayout ein?

Das GridBagLayout ist das flexibelste der Java-Layoutmanager. Ihm werden GridBagConstraints zugewiesen, über deren Eigenschaften wesentliche Teile der eigentlichen Konfiguration gesteuert werden.

Der Artikel erläutert die Grundlagen der Anwendung des GridBagLayout. Anhand eines einfachen Fensters mit sechs JLabel-Objekten werden die Konfigurationsmöglichkeiten beispielhaft gezeigt.

Das Beispielprogramm

Das Programm besteht neben dem Konstruktor und main() aus drei Methoden:

  1. In init() werden das Fenster als JFrame und ein JPanel erzeugt. Es wird an die Methode createLayout() übergeben und schließlich zentral auf den Frame gesetzt wird.
  2. createLabel() ist eine Hilfsmethode zur Erzeugung der JLabel-Instanzen. Ihnen werden hier lediglich eine Größe und zur besseren Unterscheidung ein Text und eine Hintergrundfarbe zugewiesen.
  3. In createLayout() wird ein GriBagLayout-Objekt erzeugt und mittels setLayout() an das Panel übergeben. Nach Erzeugen von sechs einfachen JLabel werden diese auf das Panel gesetzt.
    Bei den im Folgenden gezeigten Modifikationen des Layouts, wird lediglich diese Methode geändert, sodass der Quelltext einfach angepasst und die Beispiele nachvollzogen werden können.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class GridBagLayoutBsp {

    public GridBagLayoutBsp() {
        init();
    }

    private void init() {
        JPanel panel = new JPanel();
        createLayout(panel);
        JFrame frame = new JFrame();
        frame.add(panel);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setTitle("GridBagLayout");
        frame.setVisible(true);
    }

    private void createLayout(JPanel panel) {
        GridBagLayout gbl = new GridBagLayout();
        panel.setLayout(gbl);
        JLabel l = null;
        panel.add(createLabel(l, Color.RED, "rot"));
        panel.add(createLabel(l, Color.GREEN, "gruen"));
        panel.add(createLabel(l, Color.DARK_GRAY, "grau"));
        panel.add(createLabel(l, Color.BLUE, "blau"));
        panel.add(createLabel(l, Color.YELLOW, "gelb"));
        panel.add(createLabel(l, Color.WHITE, "weiss"));
    }

    private JLabel createLabel(JLabel label, Color c, String txt) {
        label = new JLabel(txt);
        label.setPreferredSize(new Dimension(60, 60));
        label.setOpaque(true);
        label.setBackground(c);
        return label;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new GridBagLayoutBsp());
    }
}

Beim Ausgangsbeispiel wird das verwendete GridBagLayout mit dem Standard-Konstruktor erzeugt und ohne weitere Konfiguration dem JPanel zugewiesen. Das Ergebnis ist die zwischenraumlose Anordnung der Elemente in einer Reihe von links nach rechts.

GridBagLayout ohne weitere Konfiguration

Ein Raster erzeugen

Gemeinhin ist jedoch eine rasterartige Anordnung der Elemente erwünscht. Dies wird durch Zuweisung und entsprechende Einrichtung eines Objektes der Klasse GridBagConstraints erreicht. Es bietet eine Vielzahl an Feldern, die eine kleinteilige Anordnung und Konfiguration erlauben.

GridBagLayout gbl = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
gbl.setConstraints(panel, gbc);
panel.setLayout(gbl);

Hierzu wird prinzipiell so vorgegangen, dass die jeweiligen Layout-Eigenschaften einer Komponente den Constraints zugewiesen werden und anschließend die Komponente auf dem Panel platziert wird. Dies geschieht durch die Methode add(), der als erstem Parameter die zu platzierende Komponente und als zweitem die Constraints übergeben werden.

private void createLayout(JPanel panel) {
    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();
    gbl.setConstraints(panel, gbc);
    panel.setLayout(gbl);
    JLabel l = null;
    gbc.gridx = 0;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.RED, "rot"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.GREEN, "gruen"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 1;
    panel.add(createLabel(l, Color.DARK_GRAY, "grau"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 1;
    panel.add(createLabel(l, Color.BLUE, "blau"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.YELLOW, "gelb"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.WHITE, "weiss"), gbc);
}

GridBagLayout mit drei Zeilen und zwei Spalten

Das Beispiel demonstriert, wie durch das Setzen der int-Variablen gridx und gridy, die horizontalen und vertikalen Positionen innerhalb des Rasters angegeben werden. Der Wert der ersten Position ist 0. Es muss betont werden, dass einmal gesetzte Werte so lange beibehalten werden, bis sie wieder geändert werden. Weist man verschiedenen Komponenten gleiche gridx- oder gridy-Werte zu, so werden sie auch an die gleiche Position gesetzt und ggfs. überdeckt.

Sollen Komponenten zeilen- oder spaltenübergreifend gesetzt werden, so können die Variablen gridwidth und gridheight verwendet werden. Hierbei müssen drei Dinge beachtet werden.

private void createLayout(JPanel panel) {
    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();
    gbl.setConstraints(panel, gbc);
    panel.setLayout(gbl);
    JLabel l = null;
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridwidth = 2;
    gbc.fill = GridBagConstraints.BOTH;
    panel.add(createLabel(l, Color.RED, "rot"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.gridwidth = 1;
    panel.add(createLabel(l, Color.DARK_GRAY, "grau"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 1;
    panel.add(createLabel(l, Color.BLUE, "blau"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.YELLOW, "gelb"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.WHITE, "weiss"), gbc);
}
GridBagLayout mit Überspannung zweier Spalten mit fill
GridBagLayout mit Überspannung zweier Spalten und Angabe von fill
GridBagLayout mit Überspannung zweier Spalten ohne fill
GridBagLayout mit Überspannung zweier Spalten ohne fill und ohne Wegfall des grünen Labels

Die Position einer Komponente, die kleiner ist als der ihr zugeordnete Bereich, kann durch GridBagConstraints.anchor festgelegt werden. Im Beispiel wird das zwei Felder horizontal überspannende rote Label im zur Verfügung stehenden Raum nach rechts (EAST) gesetzt, obwohl es durch Setzen von gridx=0 am Reihenbeginn links positioniert wurde.

private void createLayout(JPanel panel) {
    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();
    gbl.setConstraints(panel, gbc);
    panel.setLayout(gbl);
    JLabel l = null;
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridwidth = 2;
    gbc.anchor = GridBagConstraints.EAST;
    panel.add(createLabel(l, Color.RED, "rot"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.gridwidth = 1;
    panel.add(createLabel(l, Color.DARK_GRAY, "grau"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 1;
    panel.add(createLabel(l, Color.BLUE, "blau"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.YELLOW, "gelb"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.WHITE, "weiss"), gbc);
}
GridBagLayout mit Überspannung zweier Spalten ohne fill aber mit anchor=EAST
GridBagLayout mit Überspannung zweier Spalten ohne fill aber mit anchor=EAST

Abstände und Größenanpassungen

Die beiden Felder ipadx und ipady ermöglichen eine selektive Größenanpassung der Komponenten innerhalb des Rasters. Positive Werte (in Pixeln) bewirken eine beidseitige Vergrößerung, negative eine ebenfalls beidseitige Verringerung der Breite bzw. Höhe der Komponente.
Die Einstellungen gelten für alle Komponenten nach dem Setzen der Variablen. Die Rastergröße wird auch darüber hinaus angepasst, sodass ggf. Freiräume entstehen können.

private void createLayout(JPanel panel) {
    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();
    gbl.setConstraints(panel, gbc);
    panel.setLayout(gbl);
    JLabel l = null;
    gbc.gridx = 0;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.RED, "rot"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.GREEN, "gruen"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 1;
    panel.add(createLabel(l, Color.DARK_GRAY, "grau"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 1;
    gbc.ipadx = 15;
    panel.add(createLabel(l, Color.BLUE, "blau"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.YELLOW, "gelb"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 2;
    gbc.ipady = 50;
    panel.add(createLabel(l, Color.WHITE, "weiss"), gbc);
}
GridBagLayout mit ipadx und ipady
Die letzten drei Label sind durch Setzen von ipadx horizontal vergrößert, das letzte, weiße zusätzlich noch vertikal.

Wird ein echter Abstand zwischen den Rasterzellen bei gleichbleibender Komponentengröße benötigt, kann hierzu ein Insets-Objekt verwendet werden. Es wird an GridBagConstraints.insets übergeben und bezieht sich ebenfalls auf die darauf folgenden Zellen, sofern deren Abstände nicht bereits durch vorher gesetzte beeinflusst wurden. Insets summieren sich.

private void createLayout(JPanel panel) {
    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();
    gbl.setConstraints(panel, gbc);
    panel.setLayout(gbl);
    JLabel l = null;
    gbc.gridx = 0;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.RED, "rot"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.GREEN, "gruen"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.insets = new Insets(10, 10, 10, 10);
    panel.add(createLabel(l, Color.DARK_GRAY, "grau"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 1;
    panel.add(createLabel(l, Color.BLUE, "blau"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 2;
    gbc.insets = new Insets(0, 0, 0, 0);
    panel.add(createLabel(l, Color.YELLOW, "gelb"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.WHITE, "weiss"), gbc);
}
GridBagLayout mit Insets
Layout mit Insets der unteren beiden Reihen.
GridBagLayout mit Insets
Layout mit Insets der mittleren Reihe. Die Insets der letzten Reihe wurden wieder auf 0 gesetzt.

Verteilung von Abständen

Die beiden GridBagConstraints-Felder weightx und weigthy speichern double-Werte zwischen 0.0 und 1.0 und bestimmen die Art und Weise wie horizontale und vertikale Abstände zwischen Komponenten relativ zueinander verteilt werden. Dies zeigt sich besonders bei der Größenänderung eines Fensters.

private void createLayout(JPanel panel) {
    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();
    gbl.setConstraints(panel, gbc);
    panel.setLayout(gbl);
    JLabel l = null;
    gbc.gridx = 0;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.RED, "rot"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.GREEN, "gruen"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.weighty = 0.1;
    panel.add(createLabel(l, Color.DARK_GRAY, "grau"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 1;
    panel.add(createLabel(l, Color.BLUE, "blau"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 2;
    gbc.weighty = 0.2;
    panel.add(createLabel(l, Color.YELLOW, "gelb"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.WHITE, "weiss"), gbc);
}
Layout mit zweimaliger Änderung des
                    weighty-Wertes und leicht vertikal aufgezogenem
                    Fenster.
Layout mit zweimaliger Änderung des weighty-Wertes und leicht vertikal aufgezogenem Fenster.

Off-topic: Randabstand

Nicht direkt zum Thema GridBagLayout gehörig, dennoch in diesem Zusammenhang häufig nachgefragt, sind Methoden zur Erzeugung von Randabständen im Zusammenhang mit diesem Layoutmanager. Hierzu bieten sich zwei Vorgehensweisen an: Eine EmptyBorder kann ebenso verwendet werden wie eine leere Box.
Es muss an dieser Stelle jedoch darauf hingewiesen werden, dass eine EmptyBorder, wie im übrigen alle Ableitungen von AbstractBorder gänzlich unabhängig von allen LayoutManagern sind.

private void createLayout(JPanel panel) {
    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();
    gbl.setConstraints(panel, gbc);
    panel.setLayout(gbl);
    JLabel l = null;
    gbc.gridx = 0;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.RED, "rot"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.GREEN, "gruen"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 1;
    panel.add(createLabel(l, Color.DARK_GRAY, "grau"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 1;
    panel.add(createLabel(l, Color.BLUE, "blau"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.YELLOW, "gelb"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.WHITE, "weiss"), gbc);
    panel.setBorder(new EmptyBorder(0, 10, 100, 10));
}
Layout mit EmptyBorder um das Panel zur
                    Erzeugung von seitlichen und unteren Abständen.
Layout mit EmptyBorder um das Panel zur Erzeugung von seitlichen und unteren Abständen.

Ein gleiches Ergebnis lässt sich auch durch Hinzufügen einer unsichbaren Boxkomponente erreichen.

private void createLayout(JPanel panel) {
    GridBagLayout gbl = new GridBagLayout();
    GridBagConstraints gbc = new GridBagConstraints();
    gbl.setConstraints(panel, gbc);
    panel.setLayout(gbl);
    JLabel l = null;
    gbc.gridx = 0;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.RED, "rot"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 0;
    panel.add(createLabel(l, Color.GREEN, "gruen"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbc.weighty = 0.1;
    panel.add(createLabel(l, Color.DARK_GRAY, "grau"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 1;
    panel.add(createLabel(l, Color.BLUE, "blau"), gbc);
    gbc.gridx = 0;
    gbc.gridy = 2;
    gbc.weighty = 0.2;
    panel.add(createLabel(l, Color.YELLOW, "gelb"), gbc);
    gbc.gridx = 1;
    gbc.gridy = 2;
    panel.add(createLabel(l, Color.WHITE, "weiss"), gbc);
    gbc.weightx = 1;
    gbc.gridx = 3;
    gbc.gridy = 0;
    gbc.gridheight = 4;
    panel.add(Box.createHorizontalStrut(10), gbc);
    gbc.weighty = 1;
    gbc.gridx = 0;
    gbc.gridy = 3;
    panel.add(Box.createVerticalStrut(100), gbc);
}
Rechter und unterer Abstand durch
                    Einfügen einer Box.
Rechter und unterer Abstand durch Einfügen einer Box.