【问题标题】:Why is the GridBagLayout forcing some height on my components?为什么 GridBagLayout 会在我的组件上强制一些高度?
【发布时间】:2017-06-09 11:39:17
【问题描述】:

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

    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));
    }

一切正常:

现在,我并没有真正使用 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));
    }

现在我得到了这个怪物:

不再考虑数字 3 和 4 的高度,一切都是相同的高度。

为什么会这样?我怎样才能强制布局服从我:(?

【问题讨论】:

  • 将空白 JLabels 放入 7 和 7bis 位置。
  • 但这就是 GridBagLayout 的工作原理。如需更详细的解释,请在本网站搜索数百个类似问题。感谢您批评试图免费帮助您的人。
  • 布局现在实际上尊重组件的高度。它们更高的事实是因为34 被制作为填充两行并填充水平方向。这里真正的问题是,为什么您希望它们在更改布局条件后保持“超大” - 我同意 HovercraftFullOfEels,如果您追求“效果”,那么“填充”组件会有所帮助达到你想要的结果
  • @BhalchandraSW:他应该无论如何都应该这样做,所以你的评论不是首发。
  • @Saffron 这不是错误,这正是GridBagLayout 的工作原理——它可能对你没有意义,但GridBagLayout 是非常复杂的布局,需要理解很多可能场景,因此它优先考虑某些条件,行/列跨度在该列表中并不高

标签: java swing layout-manager gridbaglayout


【解决方案1】:

5 号的合同是 1 比 1 和第 3 行。此处的布局显然没有遵循此合同。当 y 和 height 属性不同时,数字 4 和数字 5 怎么可能具有相同的高度,甚至处于相同的位置?

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

所以,您的原始布局看起来像这样......

单元格1x1 (3) 和2x1 (4) 实际上是超大的,它们的高度是行高度12 的总和

然后您删除3x03x1 处的单元格,您会期待这样的事情......

但是,等等,GridBagLayout 很聪明,据推断,由于行跨度,第 1 行实际上是空的(组合大小为 0)所以它压缩了行,你最终得到...

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

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

所以GridBagLayout 查看单元格1x1 (3) 和2x1 (4) 并将它们的高度计算为行高度12 的总和,但是因为@ 987654350@ 加上任何东西就是任何东西,该行是“折叠”的,GridBagLayout 依赖于组件的preferred/minimum/maximum 大小来确定要使用的实际高度。

现在,我知道,你会抱怨这没有意义,因为单元格 1x1 (3) 和 2x1 (4) 开始在行 1 中,它们的height 应该影响行的高度和一切,在某种意义上他们会这样做,但是他们也会扩展两行,在GridBagLayout 的脑海中会影响结果,这就是GridBagLayout 的工作原理。

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

另一种解决方案可能是调查其他布局管理器,我推荐 MigLayout 作为起点。

现在,再次,在您抱怨它“没有意义”或“不正确”或“它一定是错误”之前 - 请记住,这就是 GridBagLayout 在过去 20 多年中的工作方式 - 这是它是如何工作的 - 你需要理解它并使用它或找到替代方案 - 很抱歉为此感到痛苦,但这就是它的方式:(

【讨论】:

  • 我支持使用 3rd 方布局管理器,其中布局要求“强调”标准要求。另一种解决方案是深入研究创建自定义布局管理器。 1+
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多