GridBagLayout的重量错误?(GridBagLayout weight bug?)

2019-09-16 11:16发布

在我的工作看起来并不正确的项目中的组件的布局,我怀疑有一个错误在Swing。 基本上,似乎发生的是, weightxweighty比例不被粘附时被布置在细胞已变化的最小尺寸和/或优选的尺寸以。 我创建了一个示例程序来证明这一点,这里是源:

package com.ensoftcorp.product.simmerge.gui.swing.dialogs;

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

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestClass {

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            new TestClass();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static final GridBagConstraints GBC_CELL = new GridBagConstraints();
    static final GridBagConstraints GBC_ROWEND = new GridBagConstraints();
    static final GridBagConstraints GBC_FILLROW = new GridBagConstraints();
    static {
        GBC_CELL.anchor = GridBagConstraints.NORTHWEST;
        GBC_CELL.weightx = 0.5;
        GBC_CELL.fill = GridBagConstraints.BOTH;

        GBC_ROWEND.gridwidth = GridBagConstraints.REMAINDER;

        GBC_FILLROW.gridwidth = GridBagConstraints.REMAINDER;
        GBC_FILLROW.weightx = 1.0;
        GBC_FILLROW.fill = GridBagConstraints.BOTH;
    }

    public TestClass() {
        JFrame frame = new JFrame();

        JPanel pnlContent = new JPanel(new GridBagLayout());
        pnlContent.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

        /*
         * Layout "ruler" panel
         */
        JPanel pnlRuler = new JPanel(new GridBagLayout());

        pnlRuler.add(createRulerCell(Color.BLACK, Color.WHITE),GBC_CELL);
        pnlRuler.add(createRulerCell(Color.BLACK, Color.WHITE),GBC_CELL);

        pnlRuler.add(Box.createHorizontalGlue(),GBC_ROWEND);

        /*
         * Layout "correct" panel
         */
        JPanel pnlGoodLayout = new JPanel(new GridBagLayout());

        pnlGoodLayout.add(new JButton("JButton1"),GBC_CELL);
        pnlGoodLayout.add(new JButton("JButton2"),GBC_CELL);

        pnlGoodLayout.add(Box.createHorizontalGlue(),GBC_ROWEND);

        pnlGoodLayout.add(new JButton("JButton3"),GBC_CELL);
        pnlGoodLayout.add(new JButton("JButton4"),GBC_CELL);

        pnlGoodLayout.add(Box.createHorizontalGlue(),GBC_ROWEND);

        /*
         * Layout "incorrect" panel
         */
        JPanel pnlBadLayout = new JPanel(new GridBagLayout());

        pnlBadLayout.add(new JButton("JButton1"),GBC_CELL);
        pnlBadLayout.add(new JButton("JButton2"),GBC_CELL);

        pnlBadLayout.add(Box.createHorizontalGlue(),GBC_ROWEND);

        pnlBadLayout.add(new JButton("JButton number 3 is wide"),GBC_CELL);
        pnlBadLayout.add(new JButton("JButton4"),GBC_CELL);

        pnlBadLayout.add(Box.createHorizontalGlue(),GBC_ROWEND);

        /*
         * Add panels to main panel
         */
        pnlContent.add(pnlRuler,GBC_FILLROW);
        pnlContent.add(Box.createVerticalStrut(8),GBC_FILLROW);
        pnlContent.add(pnlGoodLayout,GBC_FILLROW);
        pnlContent.add(Box.createVerticalStrut(8),GBC_FILLROW);
        pnlContent.add(pnlBadLayout,GBC_FILLROW);

        /*
         * Configure frame
         */
        frame.getContentPane().add(pnlContent);
        frame.setTitle("GridBagLayout Weight Bug?");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400,200);
        frame.setVisible(true);
}

    JComponent createRulerCell(Color border, Color background) {
        JPanel glue = new JPanel();
        glue.setBorder(BorderFactory.createLineBorder(border));
        glue.setBackground(background);

        return glue;
    }

}

示例程序有三个组...第一个是各种各样的“尺子”,显示50%的大关。 所述第二和第三组是使用的GridBagLayout其中每个单元具有一个面板weightx 0.5。 组与组之间的唯一区别是按钮上的文字长度,但第二组甚至没有均匀的比例列尽管它有足够的空间来做到这一点。

那么我的问题是:有没有人遇到过这个问题,有一个解决办法,他们将建议?

PS - 我使用jdk1.6.0_11,如果有差别。

Answer 1:

从GridBagConstraints.weightx的JavaDoc :

指定如何分布额外的水平空间。

网格包布局管理器计算出列的权重设置为列中所有组件的最大的weightx。 如果得到的布局在水平方向上比需要填充的区域,额外的空间分配给每一列与它的重量。

考虑到这一点,我不认为这是一个错误,因为与宽按钮栏计算为需要更多的空间。 一旦与正常按钮的列尺寸calced,剩余的空间分布。

解决方法:

要解决这个问题,你可以设置GBC_CELL.gridxGBC_CELL.gridy将每个按钮之前,这股与大按钮排按钮之前,您可以设置

GBC_CELL.ipadx=100;

然后将其设置为0添加宽按钮之前(#3)。 这应该对齐多一格的按钮。



Answer 2:

使用内置的GroupLayout 。 你有比GridBagLayout的更多的控制。



Answer 3:

这可能有助于(来源) :

当不止一个列具有非零权重的,多余的空间是使用权重值的非零权重的列之间分配。 特别是,如果过量的空间为P像素,以及列权重为列^ i是重量^ I,然后柱^ I恰好获得(重量^ I * P)/(加总所有列权重)。 例如,如果第1列具有权重1和柱2具有重2和过量的空间是90个像素,第1列将得到30个额外的像素和第2列将得到60个额外的像素。 行用类似的方式非零权重的行为。



Answer 4:

我发现了一个简单的解决方法。 明确设置preferredSize.width各属性JButtonpreferredSize.width=0

这是为了做到这一点:

private JButton createButton(String text) {
    JButton button = new JButton(text);
    button.setPreferredSize(new Dimension(0, button.getPreferredSize().height));
    return button;
}

下面是修改后的示例(我打上了变化// <==============评论):

public class TestClass {

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            new TestClass();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static final GridBagConstraints GBC_CELL = new GridBagConstraints();
    static final GridBagConstraints GBC_ROWEND = new GridBagConstraints();
    static final GridBagConstraints GBC_FILLROW = new GridBagConstraints();
    static {
        GBC_CELL.anchor = GridBagConstraints.NORTHWEST;
        GBC_CELL.weightx = 0.5;
        GBC_CELL.fill = GridBagConstraints.BOTH;

        GBC_ROWEND.gridwidth = GridBagConstraints.REMAINDER;

        GBC_FILLROW.gridwidth = GridBagConstraints.REMAINDER;
        GBC_FILLROW.weightx = 1.0;
        GBC_FILLROW.fill = GridBagConstraints.BOTH;
    }

    public TestClass() {
        JFrame frame = new JFrame();

        JPanel pnlContent = new JPanel(new GridBagLayout());
        pnlContent.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));

        /*
         * Layout "ruler" panel
         */
        JPanel pnlRuler = new JPanel(new GridBagLayout());

        pnlRuler.add(createRulerCell(Color.BLACK, Color.WHITE),GBC_CELL);
        pnlRuler.add(createRulerCell(Color.BLACK, Color.WHITE),GBC_CELL);

        pnlRuler.add(Box.createHorizontalGlue(),GBC_ROWEND);

        /*
         * Layout "correct" panel
         */
        JPanel pnlGoodLayout = new JPanel(new GridBagLayout());

        pnlGoodLayout.add(createButton("JButton1"),GBC_CELL); // <==============
        pnlGoodLayout.add(createButton("JButton2"),GBC_CELL); // <==============

        pnlGoodLayout.add(Box.createHorizontalGlue(),GBC_ROWEND);

        pnlGoodLayout.add(createButton("JButton3"),GBC_CELL); // <==============
        pnlGoodLayout.add(createButton("JButton4"),GBC_CELL); // <==============

        pnlGoodLayout.add(Box.createHorizontalGlue(),GBC_ROWEND);

        /*
         * Layout "incorrect" panel
         */
        JPanel pnlBadLayout = new JPanel(new GridBagLayout());

        pnlBadLayout.add(createButton("JButton1"),GBC_CELL); // <==============
        pnlBadLayout.add(createButton("JButton2"),GBC_CELL); // <==============

        pnlBadLayout.add(Box.createHorizontalGlue(),GBC_ROWEND);

        pnlBadLayout.add(createButton("JButton number 3 is wide"),GBC_CELL); // <==============
        pnlBadLayout.add(createButton("JButton4"),GBC_CELL); // <==============

        pnlBadLayout.add(Box.createHorizontalGlue(),GBC_ROWEND);

        /*
         * Add panels to main panel
         */
        pnlContent.add(pnlRuler,GBC_FILLROW);
        pnlContent.add(Box.createVerticalStrut(8),GBC_FILLROW);
        pnlContent.add(pnlGoodLayout,GBC_FILLROW);
        pnlContent.add(Box.createVerticalStrut(8),GBC_FILLROW);
        pnlContent.add(pnlBadLayout,GBC_FILLROW);

        /*
         * Configure frame
         */
        frame.getContentPane().add(pnlContent);
        frame.setTitle("GridBagLayout Weight Bug?");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400,200);
        frame.setVisible(true);
    }

    JComponent createRulerCell(Color border, Color background) {
        JPanel glue = new JPanel();
        glue.setBorder(BorderFactory.createLineBorder(border));
        glue.setBackground(background);

        return glue;
    }

    private JButton createButton(String text) {
        JButton button = new JButton(text);
        button.setPreferredSize(new Dimension(0, button.getPreferredSize().height));
        return button;
    }

}

这是结果的外观。 看到? 现在的空间是均匀分布的:



文章来源: GridBagLayout weight bug?