我正在处理的项目中的组件布局看起来不正确,我怀疑Swing中存在一个错误。基本上,似乎正在发生的是当布置的细胞具有不同的最小尺寸和/或优选尺寸时,weightx
和weighty
比例不被遵守。我创建了一个示例程序来演示这个,这里是源代码:
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。组之间的唯一区别是按钮文本长度,但第二组没有均匀分配列,即使它有足够的空间来执行此操作。
我的问题是:之前有没有人遇到过这个问题,他们会推荐一种解决方法吗?
P.S。 - 我正在使用jdk1.6.0_11,如果这有所不同。
答案 0 :(得分:5)
来自GridBagConstraints.weightx JavaDoc:
考虑到这一点,我不认为这是一个错误,因为具有宽按钮的列计算需要更多空间。一旦调整了正常按钮列大小,就会分配剩余空间。指定如何分配额外的水平空间。
网格包布局管理器计算列的权重,使其成为列中所有组件的最大权重x。如果生成的布局水平方向小于需要填充的区域,则额外的空间将按其重量的比例分配给每列。
解决方法:
要解决此问题,您可以在添加每个按钮之前设置GBC_CELL.gridx
和GBC_CELL.gridy
,在使用大按钮共享行的按钮之前,您可以设置
GBC_CELL.ipadx=100;
然后在添加宽按钮(#3)之前将其设置为0
。这应该将你的按钮对齐更多的网格。
答案 1 :(得分:2)
使用内置GroupLayout。你有比GridBagLayout更多的控制权。
答案 2 :(得分:2)
这可能会有助(source):
当多个柱的重量非零时,多余的空间为 使用权重值在非零权重列中分布。 特别是,如果多余的空间是P像素,则列权重 对于列^ i是权重^ i,然后列^ i得到正确(权重^ i * P)/ (加总所有列权重)。例如,如果第1列的权重为1 列2的权重为2,多余的空间为90像素,列为1 将获得30个额外像素,第2列将获得60个额外像素。行 非零重量的行为方式类似。
答案 3 :(得分:0)
我找到了一个简单的解决方法。将每个preferredSize.width
的{{1}}属性明确设置为JButton
。
这是做到这一点的方法:
preferredSize.width=0
以下是您修改后的示例(我使用private JButton createButton(String text) {
JButton button = new JButton(text);
button.setPreferredSize(new Dimension(0, button.getPreferredSize().height));
return button;
}
评论标记了更改):
// <==============
这就是结果的样子。看到?现在空间分布均匀: