提问者:小点点

GridBagLayout为列提供额外的边距


我在Swing工作了很长时间,终于找到了学习GridBadLayout的自信。

我仍在学习它,在这种情况下,我不明白为什么以下代码没有按预期响应:特别是我不明白为什么布局以这种方式显示列。

通过运行代码片段,您将发现代表意大利国旗的面板没有正确定位:最后一列(国旗的红色部分)与国旗的其余部分(国旗的白色部分)分离。那么,我做错了什么?为了正确地代表国旗,我可以修正什么?

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class test extends JPanel {

    private GridBagConstraints gbc;
    private final int CELL_WIDTH = 90;
    private final int CELL_HEIGHT = 110;

    public test() {
        setLayout(new GridBagLayout());

        putBanner(0);

        putFlagRow(1);
        putFlagRow(2);
        putFlagRow(3);
        putFlagRow(4);
    }

    public JPanel getUserPanel(Color c) {
        JPanel ol = new JPanel();
        ol.setPreferredSize(new Dimension(CELL_WIDTH * 10, CELL_HEIGHT));
        ol.setBackground(c);
        return ol;
    }

    public JPanel gettestPanel() {
        JPanel ol = new JPanel();
        ol.setPreferredSize(new Dimension(CELL_WIDTH, CELL_HEIGHT));
        ol.setBackground(Color.white);
        return ol;
    }

    private void putFlagRow(int gridy) {
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = gridy;
        JPanel p1=gettestPanel();
        p1.setBackground(Color.green);
        add(p1, gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 3;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 4;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 5;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 6;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 7;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 8;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 9;
        gbc.gridy = gridy;
        JPanel p=gettestPanel();
        p.setBackground(Color.red);
        add(p, gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 10;
        gbc.gridy = gridy;
        add(gettestPanel(), gbc);
    }

    private void putBanner(int gridy) {
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = gridy;
        gbc.gridwidth = 1;
        add(gettestPanel(), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = gridy;
        gbc.gridwidth = 9;
        add(getUserPanel(Color.black), gbc);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("GridBagLayoutTest");
        frame.add(new test());
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

除了了解这个特定问题及其原因之外,我还希望了解这一点,这些信息直接来自GridBagLayout Oracle文档:

weightx,weighty指定权重是一门艺术,它可以对GridBagLayout控件组件的外观产生重大影响。权重用于确定如何在列(weightx)和行(weighty)之间分配空间;这对于指定调整大小行为很重要。除非为weightx或weighty指定至少一个非零值,否则所有组件都会在其容器的中心聚集在一起。这是因为当权重为0.0(默认值)时,GridBagLayout会在其单元格网格和容器边缘之间放置任何额外的空间。通常,权重指定为0.0和1.0作为极值:必要时使用介于两者之间的数字。较大的数字表示组件的行或列应获得更多空间。对于每列,重量与该列中某个组件指定的最高重量X相关,每个多列组件的重量在组件所在的列之间以某种方式分配。类似地,每行的权重与为该行中的组件指定的最高权重相关。额外的空间倾向于朝向最右边的列和最下面的行。

表达式如下

是一门艺术

根据需要使用介于两者之间的数字

给我的印象是,即使是文档作者也不认为有可能教授这种约束的用法。这不好


共3个答案

匿名用户

最后一列(旗帜的红色部分)与旗帜的其余部分(旗帜的白色部分)分离。

调试GridBagLayout时要做的一件事是在组件中添加边框,以便查看每个单元格的大小。我在您的getTestPanel()方法中添加了以下内容:

ol.setBorder( new LineBorder(Color.BLUE) );

您可以看到面板的大小正确,但面板周围有额外的空间。

然后查看用户面板:

ol.setPreferredSize(new Dimension(CELL_WIDTH * 10, CELL_HEIGHT));

即使只将gridwidth设置为9个单元格,也会看到大小设置为10个单元格。因此,现在9个单元格必须适合用户面板的空间,并且看起来额外的空间被分配给了9列中的最后一列。

代码应该是:

//ol.setPreferredSize(new Dimension(CELL_WIDTH * 10, CELL_HEIGHT));
ol.setPreferredSize(new Dimension(CELL_WIDTH * 9, CELL_HEIGHT));

另一种选择是不给用户面板提供首选大小,但然后使用“填充”约束,这样用户面板现在将占用与九列相同的空间。

指定权重是一门艺术。。。

这与您的问题无关。要查看此效果,请将框架拖得更大。现在所有整个面板都将位于框架的中心,因为您的任何组件都不使用权重/权重约束。这意味着如果框架,没有任何组件会增长以填充空白空间。

如果其中一个组件的weightx约束为1.0,则该列将在调整帧大小时展开并填充额外的空间。

匿名用户

jutX和juty很容易使用,但是教程没有帮助...假设当您创建一个对话框并且您pack()它时,组件会占据一个位置和大小,并且一切正常(或不正常)。如果您调整对话框的大小并使其变大会发生什么?突然有更多的空间并且组件必须增长,这就是Swing查看权重*参数的时刻。

如果一个组件的权重x=1.0,其余组件的权重x=0.0,则表示第一个组件获得所有新空间,第二个组件保持其大小。如果组件的权重x=0.5,则表示这两个组件共享新的大小,各占50%。如果组件的权重x值大于1.0,则意味着组件需要的新空间大于100%,因此。。。嗯,一些神奇的东西。。。

假设您正在使用web浏览器。您希望带有选项卡、按钮和菜单的顶部面板保持相同的大小,而网页的中心面板获得所有新的额外大小,因此您为顶部面板指定了中心面板的权重*=1.0和权重*=0.0。

尽量不要在任何行或列中分配超过1.0的权重,一切都会好的。

匿名用户

我认为你试图实现的是这样的:

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test extends JPanel {

    private static final long serialVersionUID = 1L;

    public Test() {
        setLayout(new GridBagLayout());
        putBanner(0);
        putFlagRow(1);
    }

    public JPanel getUserPanel(Color c) {
        JPanel panel = new JPanel();
        panel.setBackground(c);
        return panel;
    }

    private void putFlagRow(int gridy) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = gridy;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 0.5;
        gbc.weighty = 1;
        add(getUserPanel(Color.green), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = gridy;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 1;
        gbc.weighty = 1;
        add(getUserPanel(Color.white), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = gridy;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 0.5;
        gbc.weighty = 1;
        add(getUserPanel(Color.red), gbc);
    }

    private void putBanner(int gridy) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = gridy;
        gbc.ipady = 50;
        gbc.fill = GridBagConstraints.BOTH;
        add(getUserPanel(Color.white), gbc);

        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = gridy;
        gbc.gridwidth = 2;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 1;
        add(getUserPanel(Color.black), gbc);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("GridBagLayoutTest");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setContentPane(new Test());
        frame.setSize(450, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

GridBagLayout是一种非常复杂且功能强大的内容对齐方式,用两句话来解释并不是那么容易,所以我认为最简单的方法是玩游戏或看一些教程,但我会尝试:
你必须像编辑Excel表一样思考。如果调整一个单元格的宽度,则整列的宽度与行/高度相同。因此,现在您不必添加白色平面的色调,只需添加一个并适当调整大小即可
接下来的事情不是设置固定的大小,布局会为您做这件事,这就是它们的用途或使用绝对坐标(无布局:setLayout(null))<因此,现在您必须告诉GridBagLayout如何对齐组件。不同的路线有不同的变量。首先(您应该已经知道)gridx和gridy保持组件的位置(在Excel中,如A1或C12)。然后可以将单元格与网格宽度和网格高度进行“组合”
因此,现在您的组件已定位,但它不会随着窗口的大小而更改其大小。直到知道单元格只有其组件的大小<代码>权重x和权重y是下一个要查看的变量。这些定义了应该使用多少剩余空间。例如,您有两个组件(水平并排),它们的首选宽度总和为300px,但窗口的宽度为1000px,不会使用700px。因此,如果您现在将两者的权重x都设置为1,则它们试图使用100%的剩余像素,但它们不能同时具有700px,因此每个人都接收350px。如果现在将一个权重x设置为0,另一个设置为1,则第一个没有额外的像素,另一个全部为700px
如果您一直尝试,您会看到面板之间有很多空白,这是因为只有单元格调整了大小,而没有调整其内容。现在,您可以设置组件是否应显示在其单元格中,并带有锚定(例如GridBagConstraints.NORTH),但您仍然有这些空格,并且没有标志有空格,您需要的是填充
<代码>填充用于选择如何处理单元格中的空白。使用GridBagConstraints。无不会调整组件的大小,水平仅将宽度调整为单元格的宽度(垂直仅调整高度),并且两者都调整组件的大小以适应单元格的大小
变量insets添加空insets,例如,您选择将“填充”(fill)设置为“两个”(BOTH),但sill希望组件上方有空空间(inset是固定的,如果您想要动态inset,则必须通过将空组件添加到特定的GridBagConstraints以对齐要显示的inset来解决问题)
ipadx和ipady是要添加到单元格大小的固定值,例如,如果ipadx设置为5,则单元格的宽度至少为组件的最小宽度加上ipadx的5px。换言之,单元格的宽度将始终至少比组件的宽度大5px(如果将“填充”(fill)设置为“二者”(BOTH)或“水平”(HORIZONTAL),则组件随后将调整为新宽度)。