我注意到,如果您尝试在LEADING
中使用GroupLayout
对齐,当其中一个组件是按钮而另一个组件不是按钮时,组件就不再对齐。
如果两个组件都是按钮,则会得到如下结果:
getContainerGap(button, EAST, container) -> 14
getContainerGap(another button, EAST, container) -> 14
getContainerGap(button, WEST, container) -> 14
getContainerGap(another button, WEST, container) -> 14
getContainerGap(button, SOUTH, container) -> 17
getPreferredGap(another button, button, RELATED, SOUTH, container) -> 4
getContainerGap(another button, SOUTH, container) -> 17
如果你拿出标尺,可以看到左边距恰好是20像素,所以这个结果是正确的。
如果其中一个组件不一个按钮(通常我在尝试将按钮对齐到JScrollPane
或类似的左边缘时看到这个),你会得到结果如下:
getContainerGap(button, EAST, container) -> 14
getContainerGap(reference component, EAST, container) -> 20
getContainerGap(button, WEST, container) -> 14
getContainerGap(reference component, WEST, container) -> 20
getContainerGap(button, SOUTH, container) -> 17
getPreferredGap(reference component, button, RELATED, SOUTH, container) -> 7
getContainerGap(reference component, SOUTH, container) -> 20
现在如果你拿出标尺,红色边框的左边距恰好是20像素,但按钮会突出另外6个像素。
存在getVisualMargin
方法来纠正此问题,您可以看到getContainerGap(button, EAST, container)
返回14
,这会补偿按钮外的6个像素的额外边距。
如果要布置更多类型的组件,结果会逐渐变差,最终会在布局中一直呈现锯齿状边缘,因为只有相似的组件才会相互对齐。
我想知道这里发生了什么。即使LayoutStyle
返回容器间隙的正确值,似乎GroupLayout
丢弃了值并使用了另一个组件中的值,这可以保证布局错误。< / p>
测试程序来源:
import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.LayoutStyle;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
public class ButtonVisualMarginTest implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new ButtonVisualMarginTest());
}
@Override
public void run() {
LayoutStyle.setInstance(new AquaLayoutStyle());
JComponent reference = new JComponent() {};
reference.setName("reference component");
reference.setPreferredSize(new Dimension(200, 50));
reference.setMaximumSize(new Dimension(200, 50));
reference.setBorder(BorderFactory.createLineBorder(Color.RED));
// JButton reference = new JButton("Another button");
// reference.setName("another button");
// reference.setFocusable(false);
JButton button = new JButton("Text only");
button.setName("button");
button.setFocusable(false);
JPanel container = new JPanel();
container.setName("container");
GroupLayout layout = new GroupLayout(container);
layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);
container.setLayout(layout);
container.setBackground(new Color(192, 192, 255));
container.setOpaque(true);
layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(reference)
.addComponent(button));
layout.setVerticalGroup(layout.createSequentialGroup()
.addComponent(reference)
.addComponent(button));
JFrame frame = new JFrame("Test");
frame.setLayout(new BorderLayout());
frame.add(container, BorderLayout.CENTER);
frame.setSize(400, 300);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
我试图使用的AquaLayoutStyle的略微修改版本是here(它太大而无法包含。)
因为人们可能很好奇,所以 使用AquaLayoutStyle
的结果是:
以下是使用Xcode在可滚动组件旁边布置按钮时所获得的布局(如果我们希望Java应用程序看起来像本机,那么这就是我们的目标。)