我注意到,如果您尝试在其中一个组件是按钮而另一个不是按钮时使用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 像素,所以这个结果是正确的。
如果其中一个组件不是按钮(通常我在尝试将按钮与 aJScrollPane
或类似的左边缘对齐时会看到这种情况),则会得到如下结果:
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)
return 14
,它补偿了按钮外部 6 个像素的额外边距。
如果您有更多类型的组件要布局,结果会越来越差,并且您最终会在整个布局中出现锯齿状边缘,因为只有相似的组件才会相互对齐。
我想知道这里发生了什么。尽管LayoutStyle
为容器间隙返回了正确的值,但似乎GroupLayout
是在丢弃该值并使用来自其他组件的值,这保证了布局将是错误的。
测试程序源码:
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 的略微修改版本在这里(它太大而无法包含。)
因为人们可能会好奇,所以这里是不使用的结果AquaLayoutStyle
:
这是使用 Xcode 在可滚动组件旁边布置按钮时得到的布局(如果我们希望 Java 应用程序看起来像原生,这就是我们应该瞄准的目标。)