网格袋布局:等分单元格

13

使用GridBagLayout管理器是否能完全模拟GridLayout的行为?

基本上,我有一个8x8的网格,在其中每个单元格都应该具有相同的宽度和高度。GridLayout自动完成了这个任务。但是我想在网格中添加另一行和列,其大小与其他行/列不同。那一行/列应该占用所有可能剩余的空间(因为可用空间无法平均分配为8个单元格)。这是否可能,还是我必须再次使用不同的布局管理器?

编辑

这是我要实现的简单图形,简化为仅4个单元格: Problem graphic

已添加到实际网格(灰色)中的单元格是彩色的,该网格的单元格具有相同的高度和宽度x。 因此,网格的高度和宽度为4 * x。 现在我希望附加单元格具有所需的宽度/高度(minimumSize),以及来自全尺寸的其余可用宽度/高度。

如果更改整个面板的大小,则灰色网格单元格应再次尽可能占据空间。

5个回答

3
将固定单元格的 GridBagConstraintsweightxweighty 设置为 0,并将 fill 设置为 NONE。对于浮动单元格,将 fill 设置为 BOTH,对于仅水平扩展的浮动单元格,将 weightx 设置为 1,对于垂直扩展的浮动单元格,将 weighty 设置为 1
只有填充了内容的单元格才会扩展,因此您需要使用一些内容来填充它。我选择使用 JLabel 并为固定单元格中的标签设置固定尺寸。在调整大小时,您需要重新计算尺寸并调用 invalidate() 来重新计算布局。
以下是一个 w x h 网格的示例:
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class GridBag {
    public static void main(String[] args) {
        final JFrame f = new JFrame("Gridbag Test");
        final Container c = f.getContentPane();
        c.setLayout(new GridBagLayout());

        final Dimension dim = new Dimension(70, 70);
        final int w = 4;
        final int h = 4;
        final JLabel[] yfloating = new JLabel[w];
        final JLabel[] xfloating = new JLabel[h];
        final JLabel[][] fixed = new JLabel[w][h];

        // adding the vertically floating cells
        final GridBagConstraints gc = new GridBagConstraints();
        gc.fill = GridBagConstraints.BOTH;
        gc.weightx = 0.0;
        gc.weighty = 1.0;
        for(int i = 0; i < w; ++i) {
            yfloating[i] = new JLabel("floating " + i);
            yfloating[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
            yfloating[i].setHorizontalTextPosition(JLabel.CENTER);
            yfloating[i].setVerticalTextPosition(JLabel.CENTER);
            gc.gridy = 0;
            gc.gridx = i+1;
            c.add(yfloating[i], gc);
        }

        // adding the horizontally floating cells
        gc.fill = GridBagConstraints.BOTH;
        gc.weightx = 1.0;
        gc.weighty = 0.0;
        for(int i = 0; i < w; ++i) {
            xfloating[i] = new JLabel("floating " + i);
            xfloating[i].setBorder(BorderFactory.createLineBorder(Color.BLACK));
            xfloating[i].setHorizontalTextPosition(JLabel.CENTER);
            xfloating[i].setVerticalTextPosition(JLabel.CENTER);
            gc.gridy = i+1;
            gc.gridx = 0;
            c.add(xfloating[i], gc);
        }

        // adding the fixed cells
        gc.fill = GridBagConstraints.NONE;
        gc.weightx = 0.0;
        gc.weighty = 0.0;
        for(int i = 0; i < w; ++i) {
            for(int j = 0; j < h; ++j) {
                fixed[i][j] = new JLabel("fixed " + i);
                fixed[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
                fixed[i][j].setMaximumSize(dim);
                fixed[i][j].setMinimumSize(dim);
                fixed[i][j].setPreferredSize(dim);

                gc.gridx = i+1;
                gc.gridy = j+1;
                c.add(fixed[i][j], gc);
            }
        }

        c.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentResized(ComponentEvent e) {
                final Component comp = e.getComponent();
                final int newSize = Math.min(comp.getHeight() / h, comp.getWidth() / w);
                final Dimension newDim = new Dimension(newSize, newSize);
                for(int i = 0; i < w; ++i) {
                    for(int j = 0; j < h; ++j) {
                        fixed[i][j].setMaximumSize(newDim);
                        fixed[i][j].setMinimumSize(newDim);
                        fixed[i][j].setPreferredSize(newDim);
                    }
                }
                comp.invalidate();
            }
        });

        f.pack();
        f.setVisible(true);
    }
}

1

如果您不一定要使用GridBagLayout,可以考虑使用MigLayout库。您可以按照以下方式进行操作:

MigLayout layout = new MigLayout(
        "",         // Layout Constraints
        "[10][10][10][10]", // Column constraints
        "[10][10][10][10]");  // Row constraints

阅读了这个布局管理器的快速入门指南后,我认为它基本上就是 GridBagLayout 希望成为的样子。它的工作方式类似于 GridBagLayout,但似乎更简单、更明确定义。 - Variadicism

0

0

所有的值都在GridBagConstraints中设置。

如果您想要固定8x8网格,可以设置ipadxipady值。

然后将新行/列的weightxweighty值设置为1.0,并将fill设置为FULL

您的额外行/列将随剩余空间扩展。

如果您还想扩展8x8网格,那就更复杂了。除了weightxweighty值之外,您还可以调整ipadxipady值。或者为8x8网格制作一个面板,并在其中使用GridLayout。在面板和附加的行/列上使用您的GridBagLayout


是的,我希望实际网格根据需要扩展,每行/列有8个单元格相等大小,第9个单元格具有一些最小宽度/高度和其余可用宽度/高度。我不确定额外的面板是否有效,因为额外的行应该有9个单元格,与网格的其余部分具有相同的宽度,而额外的列则应该有9个单元格,与其余部分具有相同的高度。基本上,额外的行/列应包含单元格的标签。 - poke
fill 设置为 FULL?在 GridBagConstraints 中没有 FULL 常量(也没有 FILL)。 - Bowi

-2

在尝试了许多内置布局管理器后,我决定为这个问题创建一个自定义布局管理器。由于我没有时间继续这个项目,所以我还没有完成它,但是当我完成它时,我会确保在此处发布布局管理器代码,以便任何对类似解决方案感兴趣的人都可以使用它。

编辑

didxga 在评论中提醒我要发布我的解决方案。然而,在挖掘出当时的项目并查看它之后,我实际上无法发布我的解决方案,因为事实证明我从未创建过它!

那是一个大学项目,于2010年9月中旬正式结束。我们实际上想在之后继续开发它,这可能就是我说我会发布它的原因(因为那是我想改进的一件事),但我们从来没有真正去做它 - 很遗憾。相反,我只是省略了那些额外的列和行(顺便说一下,它们是用作行/列标签的)。

所以,很抱歉我不能发布最初想要的布局... :( 如果有足够多的人请求这样的布局,也许我会创建它,但目前我不想再深入研究Java布局了 ;)


你忘记发布了,是吗? :) - didxga
@didxga 很好的观点,我完全忘记了这一点。我会尝试找出来并编辑我的答案 :) - poke
+1 我:-)不明白:-)发生了什么,没有任何与GridBadLayout、SpringLayout或eeeeght相关的问题,特别是活着的太老的线程被downvoting(布局管理器API中的一些更改)。 - mKorbel
@mKorbel 自己编写 LayoutManager 几乎总是一个不好的主意。它往往能够正常工作,除非出现以下情况:当您更改周围的布局约束时,或者当新版本的 Swing 假定比自制的 LayoutManager 更多的事情,而自制的 LayoutManager 没有观察到 - 除非在新解释实际上很重要的边缘情况下,否则您将不会注意到。这是使您的代码脆弱的好方法,除非您投入精力跟进所有关于 Swing 的新闻。 - toolforger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接