0

我注意到,如果您尝试在其中一个组件是按钮而另一个不是按钮时使用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

不使用 AquaLayoutStyle 的结果

这是使用 Xcode 在可滚动组件旁边布置按钮时得到的布局(如果我们希望 Java 应用程序看起来像原生,这就是我们应该瞄准的目标。)

相似组件的原生布局

4

0 回答 0