GridBagLayout 中的不均匀列

Uneven columns in GridBagLayout

我想创建一个由 4 个组件组成的 JPanel,它们分布在 2 列中。左列中的上部组件应占垂直 space 的 60%,下部组件应占剩余的 40%。在右栏中,它应该是相反的——上部组件占 40%,下部组件占 60%。

所以基本上我希望我的组件像这张图片一样布置:

我正在尝试通过 GridBagLayout 实现此行为。

public class Test extends JFrame {
JPanel testPanel = new JPanel();

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

Test() {
    prepareTestPanel();
    setContentPane(testPanel);
    setSize(500, 500);
    setTitle("Test");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

private void prepareTestPanel() {
    testPanel.setLayout(new GridBagLayout());
    addComp(makeUpperLeft());
    addComp(makeLowerLeft());
    addComp(makeUpperRight());
    addComp(makeLowerRight());
}

private void addComp(Pair p) {
    testPanel.add(p.comp, p.gbc);
}

private Pair makeUpperLeft() {
    JPanel panel = new JPanel();
    panel.setBorder(BorderFactory.createTitledBorder("Upper Left"));

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.gridheight = 60;
    gbc.gridwidth = 50;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.anchor = GridBagConstraints.LINE_START;
    gbc.weightx = 0.5;
    gbc.weighty = 0.6;

    return new Pair(panel, gbc);
}

private Pair makeLowerLeft() {
    JPanel panel = new JPanel();
    panel.setBorder(BorderFactory.createTitledBorder("Lower Left"));

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 60;
    gbc.gridheight = 40;
    gbc.gridwidth = 50;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.anchor = GridBagConstraints.LINE_START;
    gbc.weightx = 0.5;
    gbc.weighty = 0.4;

    return new Pair(panel, gbc);
}

private Pair makeUpperRight() {
    JPanel panel = new JPanel();
    panel.setBorder(BorderFactory.createTitledBorder("Upper Right"));

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 50;
    gbc.gridy = 0;
    gbc.gridheight = 40;
    gbc.gridwidth = 50;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.anchor = GridBagConstraints.LINE_START;
    gbc.weightx = 0.5;
    gbc.weighty = 0.4;

    return new Pair(panel, gbc);
}

private Pair makeLowerRight() {
    JPanel panel = new JPanel();
    panel.setBorder(BorderFactory.createTitledBorder("Lower Right"));

    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 50;
    gbc.gridy = 40;
    gbc.gridheight = 60;
    gbc.gridwidth = 50;
    gbc.fill = GridBagConstraints.BOTH;
    gbc.anchor = GridBagConstraints.LINE_START;
    gbc.weightx = 0.5;
    gbc.weighty = 0.6;

    return new Pair(panel, gbc);
}


private class Pair {
    Component comp;
    GridBagConstraints gbc;

    public Pair(Component comp, GridBagConstraints gbc) {
        this.comp = comp;
        this.gbc = gbc;
    }
}
}

不幸的是我得到的是:

我应该如何更正我的代码?另外,无论 window 如何调整大小,我都希望这个比例保持不变。我应该如何设置weighty

这不能直接在一个容器内完成。您将必须为您的两个列创建两个容器元素(比如另外两个 JPanel 对象)。在外部容器中添加列,然后在内部面板中添加组件。这是执行此操作的一些代码:

public class Test extends JFrame {
public Test() {

    JPanel testPanel = new JPanel();
    setContentPane(testPanel);
    GridBagLayout gbl_testPanel = new GridBagLayout();
    gbl_testPanel.columnWidths = new int[]{0, 0};
    gbl_testPanel.rowHeights = new int[]{0};
    gbl_testPanel.columnWeights = new double[]{0.5, 0.5};
    gbl_testPanel.rowWeights = new double[]{1.0};
    testPanel.setLayout(gbl_testPanel);

    JPanel leftPanel = new JPanel();
    GridBagConstraints gbc_leftPanel = new GridBagConstraints();
    gbc_leftPanel.fill = GridBagConstraints.BOTH;
    gbc_leftPanel.insets = new Insets(0, 0, 0, 5);
    gbc_leftPanel.gridx = 0;
    gbc_leftPanel.gridy = 0;
    testPanel.add(leftPanel, gbc_leftPanel);
    GridBagLayout gbl_leftPanel = new GridBagLayout();
    gbl_leftPanel.columnWidths = new int[]{0};
    gbl_leftPanel.rowHeights = new int[]{0, 0};
    gbl_leftPanel.columnWeights = new double[]{0.0};
    gbl_leftPanel.rowWeights = new double[]{0.6, 0.4};
    leftPanel.setLayout(gbl_leftPanel);

    JLabel lbl00 = new JLabel("Upper Left");
    GridBagConstraints gbc_lbl00 = new GridBagConstraints();
    gbc_lbl00.anchor = GridBagConstraints.NORTH;
    gbc_lbl00.fill = GridBagConstraints.HORIZONTAL;
    gbc_lbl00.insets = new Insets(0, 0, 5, 0);
    gbc_lbl00.gridx = 0;
    gbc_lbl00.gridy = 0;
    leftPanel.add(lbl00, gbc_lbl00);

    JLabel lbl10 = new JLabel("Lower Left");
    GridBagConstraints gbc_lbl10 = new GridBagConstraints();
    gbc_lbl10.anchor = GridBagConstraints.NORTH;
    gbc_lbl10.fill = GridBagConstraints.HORIZONTAL;
    gbc_lbl10.gridx = 0;
    gbc_lbl10.gridy = 1;
    leftPanel.add(lbl10, gbc_lbl10);

    JPanel rightPanel = new JPanel();
    GridBagConstraints gbc_rightPanel = new GridBagConstraints();
    gbc_rightPanel.fill = GridBagConstraints.BOTH;
    gbc_rightPanel.gridx = 1;
    gbc_rightPanel.gridy = 0;
    testPanel.add(rightPanel, gbc_rightPanel);
    GridBagLayout gbl_rightPanel = new GridBagLayout();
    gbl_rightPanel.columnWidths = new int[]{0};
    gbl_rightPanel.rowHeights = new int[]{0, 0};
    gbl_rightPanel.columnWeights = new double[]{0.0};
    gbl_rightPanel.rowWeights = new double[]{0.4, 0.6};
    rightPanel.setLayout(gbl_rightPanel);

    JLabel lbl01 = new JLabel("Upper Right");
    GridBagConstraints gbc_lbl01 = new GridBagConstraints();
    gbc_lbl01.insets = new Insets(0, 0, 5, 0);
    gbc_lbl01.fill = GridBagConstraints.HORIZONTAL;
    gbc_lbl01.anchor = GridBagConstraints.NORTH;
    gbc_lbl01.gridx = 0;
    gbc_lbl01.gridy = 0;
    rightPanel.add(lbl01, gbc_lbl01);

    JLabel lbl11 = new JLabel("Lower Right");
    GridBagConstraints gbc_lbl11 = new GridBagConstraints();
    gbc_lbl11.anchor = GridBagConstraints.NORTH;
    gbc_lbl11.fill = GridBagConstraints.HORIZONTAL;
    gbc_lbl11.gridx = 0;
    gbc_lbl11.gridy = 1;
    rightPanel.add(lbl11, gbc_lbl11);
}

}

GridBagLayout 不容易支持这个:

  1. 您不能只指定您想要的比例 gridwidth/height。如果您想要 6/4 的比例,那么您实际上需要创建 10 个大小相同的虚拟组件,然后先将它们添加到面板中。然后你可以说一个组件的网格高度等于这些虚拟组件的 4(或 6)个。

  2. weightx/y 约束仅适用于调整框架大小时的额外 space。因此,组件最初将按其首选尺寸打包,这意味着您还需要手动设置所需比例的首选尺寸。

您可以查看RelativeLayout。它确实允许您根据可用的 space 轻松创建相对大小的组件。

使用此布局的基本代码如下:

RelativeLayout rl = new RelativeLayout(RelativeLayout.Y_AXIS);
rl.setFill( true );
JPanel left = new JPanel( rl );
left.add(upperLeft, new Float(60));
left.add(lowerLeft, new Float(40));

// repeat above for the right panel

JPanel main = new JPanel( new GridLayout(0, 2) );
main.add(left);
main.add(right);

frame.add(main);