Java Swing的GridBagLayout不能填满整个框架。

3

我正在尝试构建一个类似于JProgressBar的组件,它可以显示三种状态,而不是像这里展示的两种状态。

我通过向一个布局设置为GridBagLayout的面板添加三个JLabel组件(具有三种不同的背景颜色)来构建此组件。我已经分配了对应的权重给这些标签,以便它们根据父面板的大小进行调整大小。下面是相应的示例代码:

public class CustomProgressBar {

  public static void main(String[] args) {

    JFrame frame = new JFrame("test");

    JPanel panel = new JPanel();

    double firstLabelWeight = 0.10d;
    double secondLabelWeight = 0.20d;
    double thirdLabelWeight = 1d - firstLabelWeight - secondLabelWeight;

    JLabel firstLabel = new JLabel();
    firstLabel.setOpaque(true);
    firstLabel.setBackground(Color.GREEN);

    JLabel secondLabel = new JLabel();
    secondLabel.setOpaque(true);
    secondLabel.setBackground(Color.YELLOW);

    JLabel thirdLabel = new JLabel();
    thirdLabel.setOpaque(true);
    thirdLabel.setBackground(Color.RED);

    panel.setLayout(new GridBagLayout());
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.fill = GridBagConstraints.BOTH;

    gbc.weightx = firstLabelWeight;
    gbc.weighty = 1d;
    panel.add(firstLabel, gbc);

    gbc.weightx = secondLabelWeight;
    gbc.weighty = 1d;
    panel.add(secondLabel, gbc);

    gbc.weightx = thirdLabelWeight;
    gbc.weighty = 1d;
    panel.add(thirdLabel, gbc);

    panel.setBackground(Color.BLACK);
    panel.setPreferredSize(new Dimension(157, 50));

    frame.add(panel);
    frame.setVisible(true);
    frame.pack();

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }
}

现在,这种方法的问题在于,当我尝试调整JFrame的大小时,上述三个标签未填满父面板中的完整水平空间,我们会看到如此处所示的黑色条纹。
我已经尝试设置gbc.fill和gbc.anchor参数,但仍然不起作用。
非常感谢您提供有关此问题的任何帮助!谢谢 :)

似乎是一个四舍五入的问题。当将初始宽度设置为160时,左右两侧没有黑色条纹。当缓慢调整大小时,它们会出现/消失。 - Robert Kock
黑色条纹是由于舍入误差而产生的。父面板的宽度始终为整数像素。当将它们分配给特定组件时,布局管理器会得到一些额外的像素,它不知道该放在哪里。这就是GridBagLayout的工作原理。如果这对您来说是一个严重的问题,您将不得不覆盖GridBagLayout。 - MatheM
1
请查看问题,它涉及到您所遇到的类似问题。 - MatheM
@MatheM 相关链接确实解决了我的问题。谢谢 - lohith
2个回答

2
为了解决四舍五入问题,你可以按照以下方式覆盖面板的布局: ```html

为了解决四舍五入问题,你可以按照以下方式覆盖面板的布局:

```
class MyLayout extends GridBagLayout
{
  private Component owner;

  public MyLayout(Component owner)
  {
    this.owner = owner;
  }

  @Override
  protected void adjustForGravity(GridBagConstraints constraints,
                                  Rectangle          rect)
  {
    // Adjust position and width of first (GREEN) label if necessary
    if ((rect.x > 0) && (rect.x <= 2))
    {
      rect.width += rect.x;
      rect.x = 0;
    }

    // Adjust width of last (RED) label if necessary
    int gap = owner.getWidth() - rect.x - rect.width;
    if ((gap > 0) && (gap <= 2))
      rect.width += gap;
  }

} // class MyLayout

当然,接下来要设置面板的布局方式:
panel.selLayout(new MyLayout(panel));

1
如果您使用负的Insets构建GridBagConstraints,这将不会显示底层的Panel。更改如下所示:

GridBagConstraints gbc = new GridBagConstraints(-1, -1, 1, 1, 0, 0, 10, 0, new Insets(-1, -1, -1, -1), 0, 0);

更新后的示例:
public class CustomProgressBar {

public static void main(String[] args) {

    JFrame frame = new JFrame("test");

    JPanel panel = new JPanel();

    double firstLabelWeight = 0.10d;
    double secondLabelWeight = 0.20d;
    double thirdLabelWeight = 1d - firstLabelWeight - secondLabelWeight;

    JLabel firstLabel = new JLabel();
    firstLabel.setOpaque(true);
    firstLabel.setBackground(Color.GREEN);

    JLabel secondLabel = new JLabel();
    secondLabel.setOpaque(true);
    secondLabel.setBackground(Color.YELLOW);

    JLabel thirdLabel = new JLabel();
    thirdLabel.setOpaque(true);
    thirdLabel.setBackground(Color.RED);

    panel.setLayout(new GridBagLayout());

    GridBagConstraints gbc = new GridBagConstraints(-1, -1, 1, 1, 0, 0, 10, 0, new Insets(-1, -1, -1, -1), 0, 0);

    gbc.fill = GridBagConstraints.BOTH;

    gbc.weightx = firstLabelWeight;
    gbc.weighty = 1d;
    panel.add(firstLabel, gbc);

    gbc.weightx = secondLabelWeight;
    gbc.weighty = 1d;
    panel.add(secondLabel, gbc);

    gbc.weightx = thirdLabelWeight;
    gbc.weighty = 1d;
    panel.add(thirdLabel, gbc);

    panel.setBackground(Color.BLACK);
    panel.setPreferredSize(new Dimension(157, 50));

    frame.add(panel);
    frame.setVisible(true);
    frame.pack();

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 }
}

输出:

enter image description here


更简单的方法是:创建默认约束条件"gbc = new GridBagConstraints()",然后只设置水平插入值"gbc.insets = new Insets(0, -1, 0, -1)"。 - Robert Kock
虽然这种方法简单且填充整个面板,但当其中一个标签必须填充整个面板时会出现问题。例如,在上面的示例中,将第一个和第二个标签的权重设置为零应该使用红色的第三个标签填充整个面板,但我们看到一条绿色的条纹在开头。 - lohith

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