【问题标题】:GridBagLayout weight bug?GridBagLayout 重量错误?
【发布时间】:2023-03-28 17:40:02
【问题描述】:

我正在处理的项目中组件的布局看起来不正确,我怀疑 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。组之间的唯一区别是按钮文本长度,但第二组即使有足够的空间也不会均匀地按列比例。

然后我的问题是:以前有没有人遇到过这个问题,并且有他们推荐的解决方法?

附: - 我正在使用 jdk1.6.0_11,如果这有影响的话。

【问题讨论】:

    标签: java swing layout grid


    【解决方案1】:

    来自GridBagConstraints.weightx JavaDoc

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

    网格包布局管理器将列的权重计算为列中所有组件的最大权重x。如果生成的布局在水平方向上小于它需要填充的区域,则额外的空间将按其权重按比例分配到每一列。

    考虑到这一点,我不认为这是一个错误,因为带有宽按钮的列被计算为需要更多空间。一旦计算了正常按钮列的大小,就会分配剩余空间。

    解决方法:

    要解决此问题,您可以在添加每个按钮之前设置 GBC_CELL.gridxGBC_CELL.gridy,在与大按钮共享行的按钮之前,您可以设置

    GBC_CELL.ipadx=100;

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

    【讨论】:

      【解决方案2】:

      使用内置的GroupLayout。您拥有比 GridBagLayout 更多的控制权。

      【讨论】:

        【解决方案3】:

        这可能有助于(source):

        当多于一列的权重不为零时,多余的空间为 使用权重值分布在非零权重列中。 特别是,如果多余的空间是 P 个像素,并且列权重 对于 column^i 是 weight^i,则 column^i 得到精确的 (weight^i * P) / (所有列权重的总和)。例如,如果第 1 列的权重为 1 第 2 列的权重为 2,多余的空间为 90 像素,第 1 列 将获得 30 个额外像素,第 2 列将获得 60 个额外像素。行 具有非零权重的行为类似。

        【讨论】:

          【解决方案4】:

          我找到了一个简单的解决方法。将每个JButtonpreferredSize.width 属性显式设置为preferredSize.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;
              }
          
          }
          

          这就是结果的样子。看?现在空间分布均匀了:

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-07-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-07-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多