Probleme mit einem GridbagLayout

Ich habe ein etwas komplexeres Layout für eine Reihe von Datenbanktabellen.

Ich habe dafür in 10 Zeilen und 6 Spalten die Tabellen angeordnet. Da einige Zeilen höher ausfallen sollen, wird mit gbc.gridheight gearbeitet und die “echten” Zeilennummern sind dann nicht mehr 0 bis 9, sondern 0, 2, 3, 4, 5, 8, 9, 10, 11 und 12, vergleiche getLayouts().

Nicht in jede Tabelle soll genau eine Spalte breit werden. Daher wird mit gbc.gridwidth gearbeitet.

Im Prinzip klappt das auch, nur erstaunen mich zwei Dinge:

  1. Die Zeile mit den Feldern G, H und I sieht genauso aus, wie die Zeile daunter mit den Feldern J, K und L, obwohl das Verhältnis der Spaltenanzahlen 1:2:3 statt 2:2:2 ist.

  2. Die Zeile mit Q und R sieht genauso aus, wie die Zeile daüber mit den Feldern O und P, obwohl das Verhältnis der Spaltenanzahlen 5:1 statt 4:2 ist.

Kann mich da jemand erhellen, was ich falsch gemacht habe?

Testcode:


import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.ArrayList;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;

public class GridBagLayoutTest {

    public class LayoutInfo {
        private final String tableName;
        private final int gridx;
        private final int gridy;
        private final int gridwidth;
        private final int gridheight;

        private LayoutInfo(String tableName, int gridx, int gridy,
                int gridwidth, int gridheight) {
            this.tableName = tableName;
            this.gridx = gridx;
            this.gridy = gridy;
            this.gridwidth = gridwidth;
            this.gridheight = gridheight;
        }

        public String getTableName() {
            return tableName;
        }
        public int getGridx() {
            return gridx;
        }
        public int getGridy() {
            return gridy;
        }
        public int getGridwidth() {
            return gridwidth;
        }
        public int getGridheight() {
            return gridheight;
        }
    }

    public GridBagLayoutTest() {
        final JFrame frame = new JFrame();
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createFrame(frame);
                frame.setVisible(true);
            }
        });
    }

    private void createFrame(JFrame frame) {
        setNiceLayoutManager();

        frame.setTitle("GridBagLayoutTest");
        frame.setLayout(new BorderLayout());

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createCenterPart(), BorderLayout.CENTER);

        frame.setPreferredSize(new Dimension(900, 650));
        frame.setLocation(150, 110);
        frame.pack();
    }

    public void setNiceLayoutManager() {
        try {
            UIManager.setLookAndFeel(
                    "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
        }
        catch (Exception e) {
            // nicht schlimm
        }
    }

    private Component createCenterPart() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.BOTH;

        for (LayoutInfo info : getLayouts()) {
            gbc.gridx      = info.getGridx();
            gbc.gridy      = info.getGridy();
            gbc.gridwidth  = info.getGridwidth();
            gbc.gridheight = info.getGridheight();
            gbc.weightx    = 1.0 * info.getGridwidth();
            gbc.weighty    = 1.0 * info.getGridheight();
            System.out.println("name = " + info.getTableName()
                    + ", gridx = " + gbc.gridx
                    + ", gridy = " + gbc.gridy
                    + ", gridwidth = " + gbc.gridwidth
                    + ", gridheight = " + gbc.gridheight
                    + ", weightx = " + gbc.weightx
                    + ", weighty = " + gbc.weighty);
            panel.add(createPanel(info), gbc);
        }

        return panel;
    }

    private List<LayoutInfo> getLayouts() {
        List<LayoutInfo> layouts = new ArrayList<>();

        layouts.add(new LayoutInfo("A", 0, 0, 6, 2));

        layouts.add(new LayoutInfo("B", 0, 2, 4, 1));
        layouts.add(new LayoutInfo("C", 4, 2, 2, 1));

        layouts.add(new LayoutInfo("D", 0, 3, 6, 1));

        layouts.add(new LayoutInfo("E", 0, 4, 6, 1));

        layouts.add(new LayoutInfo("F", 0, 5, 6, 3));

        layouts.add(new LayoutInfo("G", 0, 8, 1, 1));
        layouts.add(new LayoutInfo("H", 1, 8, 2, 1));
        layouts.add(new LayoutInfo("I", 3, 8, 3, 1));

        layouts.add(new LayoutInfo("J", 0, 9, 2, 1));
        layouts.add(new LayoutInfo("K", 2, 9, 2, 1));
        layouts.add(new LayoutInfo("L", 4, 9, 2, 1));

        layouts.add(new LayoutInfo("M", 0, 10, 4, 1));
        layouts.add(new LayoutInfo("N", 4, 10, 2, 1));

        layouts.add(new LayoutInfo("O", 0, 11, 3, 1));
        layouts.add(new LayoutInfo("P", 3, 11, 3, 1));

        layouts.add(new LayoutInfo("Q", 0, 12, 5, 3));
        layouts.add(new LayoutInfo("R", 5, 12, 1, 3));

        return layouts;
    }

    private Component createPanel(LayoutInfo info) {
        JPanel panel = new JPanel();
        panel.setBorder(BorderFactory.createTitledBorder(info.getTableName()));

        return panel;
    }

    public static void main(String[] args) {
        new GridBagLayoutTest();
    }

}

Die Ausgabe von System.out.println ist brav

name = A, gridx = 0, gridy = 0, gridwidth = 6, gridheight = 2, weightx = 6.0, weighty = 2.0
name = B, gridx = 0, gridy = 2, gridwidth = 4, gridheight = 1, weightx = 4.0, weighty = 1.0
name = C, gridx = 4, gridy = 2, gridwidth = 2, gridheight = 1, weightx = 2.0, weighty = 1.0
name = D, gridx = 0, gridy = 3, gridwidth = 6, gridheight = 1, weightx = 6.0, weighty = 1.0
name = E, gridx = 0, gridy = 4, gridwidth = 6, gridheight = 1, weightx = 6.0, weighty = 1.0
name = F, gridx = 0, gridy = 5, gridwidth = 6, gridheight = 3, weightx = 6.0, weighty = 3.0
name = G, gridx = 0, gridy = 8, gridwidth = 1, gridheight = 1, weightx = 1.0, weighty = 1.0
name = H, gridx = 1, gridy = 8, gridwidth = 2, gridheight = 1, weightx = 2.0, weighty = 1.0
name = I, gridx = 3, gridy = 8, gridwidth = 3, gridheight = 1, weightx = 3.0, weighty = 1.0
name = J, gridx = 0, gridy = 9, gridwidth = 2, gridheight = 1, weightx = 2.0, weighty = 1.0
name = K, gridx = 2, gridy = 9, gridwidth = 2, gridheight = 1, weightx = 2.0, weighty = 1.0
name = L, gridx = 4, gridy = 9, gridwidth = 2, gridheight = 1, weightx = 2.0, weighty = 1.0
name = M, gridx = 0, gridy = 10, gridwidth = 4, gridheight = 1, weightx = 4.0, weighty = 1.0
name = N, gridx = 4, gridy = 10, gridwidth = 2, gridheight = 1, weightx = 2.0, weighty = 1.0
name = O, gridx = 0, gridy = 11, gridwidth = 3, gridheight = 1, weightx = 3.0, weighty = 1.0
name = P, gridx = 3, gridy = 11, gridwidth = 3, gridheight = 1, weightx = 3.0, weighty = 1.0
name = Q, gridx = 0, gridy = 12, gridwidth = 5, gridheight = 3, weightx = 5.0, weighty = 3.0
name = R, gridx = 5, gridy = 12, gridwidth = 1, gridheight = 3, weightx = 1.0, weighty = 3.0

aber die Darstellung ist eine andere.

Das willst du bestimmt nicht hören, aber GridBagLayout ist einfach eine Fehlkonstruktion. Sicher gibt es Experten, die inzwischen alle seine Macken kennen, aber es ist deutlich produktiver, sich nach einem Ersatz umzusehen (MigLayout, TableLayout, FormLayout…).

5:1 statt 3:3

warum auch immer es mit der Höhe klappt, wobei auch nicht exakt 3:1-Verhältnis,
bei Spalten hat das GridBagLayout geniale Fähigkeiten, manche Spalten auf Breite 0 zusammenzukürzen, damit der Rest einfacher aussieht

meine ‚Experten‘-Lösung, die auch hier anscheinend super klappt:
oben oder unten mit Höhe 0 eine Menge von stardisierten unsichtbaren Labels einfügen:

        layouts.add(new LayoutInfo("", 0, 13, 1, 0));
        layouts.add(new LayoutInfo("", 1, 13, 1, 0));
        layouts.add(new LayoutInfo("", 2, 13, 1, 0));
        layouts.add(new LayoutInfo("", 3, 13, 1, 0));
        layouts.add(new LayoutInfo("", 4, 13, 1, 0));
        layouts.add(new LayoutInfo("", 5, 13, 1, 0));

edit:
besser noch spezifischer ohne Border usw.,
ich verstehe im Moment noch gar nicht, wieso die 13er-Zeile nicht zu sehen ist, auch wenn mit sichtbaren Daten,
sobald ich eine vorherige Zeile herausnehme, dann vorhanden…

edit: ach so, wegen Zeile 13 und davor mehrere Zeilen belegt…

Das hab ich nicht gehört. :wink:
Hmmm.

Stimmt.

den Rest meines Postings auch gelesen? :wink:

Ja, aber dem Text zufolge mehr für Weitere Verwunderungen gehalten. Aber das klappt tatsächlich! Danke.

Ich hab in meinem Originalprogramm nun in Zeile 0 nochmal sechs leere JPanels eingefügt. Sehr seltsam, dass es dann geht, vorher aber nicht.