如何使用 GridLayout 设置组件大小?有没有更好的方法?

2022-09-03 17:56:31

我正在用Java开发一个更大的GUI,我对布局管理器感到愤怒。

我有一个“设置面板”,其中包含可变数量的JComponents(标签,按钮,JSpinners,JSliders,...)。我只想要以下内容:

JLabel <-> JComponent

JLabel <-> JComponent

JLabel <-> JComponent

...

我的面板大小为500px,因此有足够的空间容纳许多组件。不幸的是,GridLayout总是将组件的大小扩展到整个面板,即使我为每个组件设置了MaxIze。如果只有两个按钮,每个按钮的高度为250px,这看起来很愚蠢。

我尝试过FlowLayout,但我无法找到一种正确制作新线条的方法。我尝试BoxLayout.Y_AXIS,但组件始终居中,标签和组件不在同一行中。

有没有人知道使用布局管理器来正确处理这个问题的好方法?


答案 1

其他布局的替代方法可能是将带有 GridLayout 的面板放在另一个 FlowLayout 面板中。这样,您的间距将保持不变,但不会在整个可用空间中扩展。


答案 2

不要将GridLayout用于它不应该做的事情。在我看来,GridBagLayout更适合你,无论是那个还是MigLayout(尽管你必须先下载它,因为它不是标准Java的一部分)。要么这样,要么组合布局管理器,如线条的BoxLayout和GridLayout来保存所有行。

例如,使用 GridBagLayout:

import java.awt.*;
import javax.swing.*;

public class LayoutEg1 extends JPanel{
    private static final int ROWS = 10;

    public LayoutEg1() {
        setLayout(new GridBagLayout());
        for (int i = 0; i < ROWS; i++) {
            GridBagConstraints gbc = makeGbc(0, i);
            JLabel label = new JLabel("Row Label " + (i + 1));
            add(label, gbc);

            JPanel panel = new JPanel();
            panel.add(new JCheckBox("check box"));
            panel.add(new JTextField(10));
            panel.add(new JButton("Button"));
            panel.setBorder(BorderFactory.createEtchedBorder());
            gbc = makeGbc(1, i);
            add(panel, gbc);
        }
    }

    private GridBagConstraints makeGbc(int x, int y) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = 1;
        gbc.gridheight = 1;
        gbc.gridx = x;
        gbc.gridy = y;
        gbc.weightx = x;
        gbc.weighty = 1.0;
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.anchor = (x == 0) ? GridBagConstraints.LINE_START : GridBagConstraints.LINE_END;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        return gbc;
    }

    private static void createAndShowUI() {
        JFrame frame = new JFrame("Layout Eg1");
        frame.getContentPane().add(new LayoutEg1());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                createAndShowUI();
            }
        });
    }
}