GridBagLayout为列

时间:2018-02-28 14:29:11

标签: java swing layout-manager 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,重量   指定权重是一种艺术,可以对GridBagLayout控制的组件的外观产生重大影响。重量是   用于确定如何在列之间分配空间(weightx)和   行之间(重量级);这对于指定调整大小很重要   行为。除非您为weightx指定至少一个非零值   或重量,所有组件在他们的中心聚集在一起   容器。这是因为当重量为0.0(默认值)时,   GridBagLayout在其单元格和网格之间放置任何额外的空间   容器的边缘。通常权重指定为0.0和   1.0作为极端:根据需要使用两者之间的数字。较大的数字表示组件的行或列应该得到   更多的空间。对于每列,权重与最高值相关   为该列中的组件指定的权重,每个权重   多列组件的权重在列之间以某种方式分开   组件是。同样,每行的权重与   为该行内的组件指定的最高权重。额外的空间   倾向于走向最右边的列和底行。

表达式

  

是一门艺术

  

中间的数字用于必要

确实给我的印象是,即使是文档作者也不认为可以教这种约束的使用。这不是好事

3 个答案:

答案 0 :(得分:2)

weightX和weighty非常容易使用,但教程没有帮助...让我们说当你进行对话并pack()它时,组件占据一个位置和大小,一切都很好(或不)。如果您调整对话框并使其变大,会发生什么?突然间有更多空间,组件必须增长,而这正是Swing查看weight*参数的时刻。

如果某个组件有weightx=1.0,其余weightx=0.0表示第一个组件获取所有新空间而第二个组件保持其大小。如果组件具有weightx=0.5,则意味着两个组件共享新大小,每个组件占50%。如果组件的weightx值大于1.0,则意味着组件需要超过100%的新空间,所以......好吧,有些神奇......

想象一下,你正在做一个网络浏览器。你希望带有标签,按钮和菜单的顶部面板保持相同的大小,而网页的中心面板获得所有新的额外尺寸,所以你给中心面板weight*=1.0和{{1}对于顶部面板。

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

答案 1 :(得分:2)

  

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

调试GridBagLayout时要做的一件事是向组件添加Border,这样您就可以看到每个单元格的大小。我在您的getTestPanel()方法中添加了以下内容:

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

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

然后你看看你的用户面板:

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

即使您只将网格宽度设置为9个单元格,您也会看到大小设置为10个单元格。所以现在9个单元格必须适合用户面板的空间,看起来额外的空间被赋予了9列的最后一列。

代码应为:

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

另一个选择是不向用户面板提供首选尺寸,但是然后使用" fill"约束因此用户面板现在将占用与九列相同的空间。

  

weightx,weighty指定权重是一门艺术......

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

如果其中一个组件的权重约束为1.0,那么当该框架调整大小时,该列将展开并填充额外的空间。

答案 2 :(得分:2)

我认为你想要实现的目标是这样的:

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如何对齐组件。不同的比对有不同的变量。首先(您应该已经知道)gridxgridy保持组件的位置(在Excel中类似于A1或C12)。你可以将“单元格”与gridwidthgridheight结合起来 所以现在您的组件已定位,但它不会随窗口大小而改变其大小。直到知道单元格只有其组件getPreferredSize()的大小。 weightxweighty是下一个要查看的变量。这些定义了应该使用多少剩余空间。例如,您有两个组件(水平并排),它们的首选宽度总和为300px,但窗口的宽度为1000px,不使用700px。因此,如果您现在将weightx都设置为1,他们会尝试使用百分之百的剩余像素,但是它们不能同时使用700px,因此每个人都会获得350px。如果你现在将一个weightx设置为0而将另一个设置为1,则第一个没有额外的像素,另一个没有700px。
如果你到现在为止尝试过,你会在面板之间看到很多空白区域,因为只有单元格被调整大小,而不是它们的内容。现在你可以设置组件应该在anchor的单元格中显示(例如GridBagConstraints.NORTH / SOUTH / SOUTHEAST),但是你仍然有那些空格和没有标志有空格,你要找的是fill fill允许您选择如何处理单元格中的空白区域。如果GridBagConstraints.NONE组件不会调整大小,HORIZONTAL只会将宽度调整为单元格的宽度(VERTICAL仅调整高度),BOTH调整组件的大小以适应细胞大小 变量insets添加了空插图,例如您选择将fill设置为BOTH,但是sill希望在组件上方留出空白(如果您想要动态,插入是固定的在插图中,您必须通过添加具有特定GridBagConstraints的空组件来对齐您要显示的插图。)
ipadxipady是要添加到单元格大小的固定值,例如ipadx设置为5,单元格将至少具有组件最小宽度的宽度加上ipadx的5px。换句话说,单元格的宽度将始终比组件的宽度大至少5px(如果fill设置为BOTHHORIZONTAL,组件之后将调整为新宽度)。