我有以下代码在面板中显示许多标签:

    private static class Bordered extends JLabel {
        public Bordered(final String text) {
            super(text);
            this.setBorder(new MatteBorder(2,2,2,2,Color.BLACK));
        }
    }

    public static void main(String[] args) {
        Frame frame = new Frame("toto");

        JPanel panel = new JPanel(new GridBagLayout());
        panel.add(new Bordered("0"), new GridBagConstraints(0,0,1,3, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("1"), new GridBagConstraints(1,0,1,1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("2"), new GridBagConstraints(2,0,1,1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("3"), new GridBagConstraints(1,1,1,2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("4"), new GridBagConstraints(2,1,1,2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("5"), new GridBagConstraints(3,2,1,1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("6"), new GridBagConstraints(4,0,1,3, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("7"), new GridBagConstraints(3,0,1,1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("7bis"), new GridBagConstraints(3,1,1,1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));


        frame.add(panel);

        frame.pack();
        SwingUtilities.invokeLater(() -> frame.setVisible(true));
    }


因为一切正常,所以:

java - 为什么GridBagLayout迫使我的组件有些高度?-LMLPHP

现在,我对7和7bis并没有真正的用途,我只是添加了它们以向您展示我想要的东西。因此,让我们删除它们:

    private static class Bordered extends JLabel {
        public Bordered(final String text) {
            super(text);
            this.setBorder(new MatteBorder(2,2,2,2,Color.BLACK));
        }
    }

    public static void main(String[] args) {
        Frame frame = new Frame("toto");

        JPanel panel = new JPanel(new GridBagLayout());
        panel.add(new Bordered("0"), new GridBagConstraints(0,0,1,3, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("1"), new GridBagConstraints(1,0,1,1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("2"), new GridBagConstraints(2,0,1,1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("3"), new GridBagConstraints(1,1,1,2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("4"), new GridBagConstraints(2,1,1,2, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("5"), new GridBagConstraints(3,2,1,1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
        panel.add(new Bordered("6"), new GridBagConstraints(4,0,1,3, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
//        panel.add(new Bordered("7"), new GridBagConstraints(3,0,1,1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));
//        panel.add(new Bordered("7bis"), new GridBagConstraints(3,1,1,1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(3, 3, 3, 3), 0, 0));


        frame.add(panel);

        frame.pack();
        SwingUtilities.invokeLater(() -> frame.setVisible(true));
    }


现在我得到了这个怪物:

java - 为什么GridBagLayout迫使我的组件有些高度?-LMLPHP

不再考虑数字3和4的高度,所有高度都相同。

为什么会这样呢?我怎样才能迫使布局服从我:(?

最佳答案

5号的合同应为1乘1并在第三行。显然,此处的布局不遵循此合同。当数字4和数字5的y和height属性不同时,它们如何具有相同的高度,甚至位于相同的位置?


您对GridBagLayout的工作方式有些误解

因此,您的原始布局看起来像这样...

java - 为什么GridBagLayout迫使我的组件有些高度?-LMLPHP

单元格1x13)和2x14)实际上过大,它们的高度是行12的高度之和

然后删除3x03x1的单元格,就可以看到类似这样的内容...

java - 为什么GridBagLayout迫使我的组件有些高度?-LMLPHP

但是,等一下,GridBagLayout很聪明,可以推断出,由于行跨度的原因,行1实际上是空的(组合大小为0),因此它压缩了行,最终结果是...

java - 为什么GridBagLayout迫使我的组件有些高度?-LMLPHP

您可能会认为这是“错误的”,但事实并非如此,并且需要花费一些时间来思考实际发生的情况。

实际上唯一对行1的高度有影响的单元格是单元格3x1,从技术上讲,它现在的大小为0,因为那里什么都没有,所以行高变成了0(也(1x11x2的单元格的首选高度小于之前跨度的两行的总和,也有影响)

因此GridBagLayout查看单元格1x13)和2x14)并将其高度计算为行12的高度之和,但是因为0加任何都是什么,该行是“折叠的”,GridBagLayout依赖于组件的preferred/minimum/maximum大小来确定要使用的实际高度。

现在,我知道,您将抱怨这没有意义,因为单元格1x13)和2x14)从行1开始,它们的高度会影响从某种意义上说,行的高度和所有内容的高度都可以,但是随后它们又扩展了两行,这在GridBagLayout的思想中对结果有影响,这正是GridBagLayout的工作方式。

那么,有什么解决方案?是否喜欢,如果不希望布局不压缩,则需要在3x2处提供某种具有所需行高的组件。我知道,这不是一个很好的解决方案,过去我做了很多不同的修改来使其工作(使用JLabel,其前景色与容器的背景色相同,或者具有前景色完全透明的颜色,我什至使用了自己的布局管理器,该管理器忽略了组件的visible属性,以使其保持容器的大小相同,因此我可以“隐藏”和“显示”组件而无需压缩布局)

另一个解决方案可能是调查其他布局管理器,我建议以MigLayout作为起点。

现在,再次,在您抱怨它“没有意义”或“不正确”或“它一定是错误”之前-记住,这是GridBagLayout在过去20多年的工作方式-这是它的工作方式-您需要了解它并使用它,或者找到其他选择-很抱歉让您感到痛苦,但这只是它的方式:(

07-24 09:49
查看更多