当 JLabel 包含 HTML 时,BoxLayout 不遵守胶水

BoxLayout doesn't respect glue when JLabel contains HTML

我编写了一个组件,它使用 BoxLayout 水平布局一些 JLabel,然后是胶水(我希望 JLabel 的宽度保持固定)。例如:

我需要向每个 JLabel 添加两行文本,所以我使用了一些 HTML。一旦我添加了 HTML,BoxLayout 就不再依赖胶水了。我得到类似的东西:

我可以通过指定最大大小应等于首选大小来解决这个问题(指定首选大小无效)。这是正确的方法吗?是否有一些解释为什么当我的 JLabel 中有 HTML 时胶水似乎被忽略了?

MWE:

import javax.swing.*;
import java.awt.*;

public class LabelBreak extends JFrame {

JPanel panel;

public LabelBreak() {
    setTitle("Frame");
    panel = new MyPanel();
    panel.setPreferredSize(new Dimension(500, 100));
    add(panel);
}

public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
        JFrame frame = new LabelBreak();
        frame.pack();
        frame.setVisible(true);
    });
}

private static class MyPanel extends JPanel {
    private MyPanel() {
        super();
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        JPanel header = new JPanel();
        header.setLayout(new BoxLayout(header, BoxLayout.X_AXIS));
        //JLabel label = new JLabel("One");
        JLabel label = new JLabel("<html>One<br>is<br>the<br>loneliest<br>number</html>");
        label.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
        header.add(label);
        label = new JLabel("Two");
        label.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
        header.add(label);
        header.add(Box.createHorizontalGlue());
        this.add(header);
    }
}
}

BoxLayout 遵守 JLabel 的最大大小,因此您必须设置它。

要控制两个标签之间的宽度,您可以使用 Box.createHorizontalStrut(width)

请注意,两个标签位于 header 的中心。我会使用 GridLayout 将组件放在一行中,列之间有不同的 space。

private MyPanel() {
            super();
            this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            JPanel header = new JPanel();
            header.setLayout(new GridLayout(1,4,20,0));
            // JLabel label = new JLabel("One");
            JLabel label = new JLabel("<html>One<br>is<br>the<br>loneliest<br>number</html>");
            label.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
            label.setMaximumSize(label.getPreferredSize());
            header.add(label);
//          header.add(Box.createHorizontalStrut(10));
            label = new JLabel("Two");
            label.setBorder(BorderFactory.createLineBorder(Color.RED, 2));
            header.add(label);
            // header.add(Box.createHorizontalGlue());
            this.add(header);
        }

Is there some explanation for why glue seems to be ignored when there's HTML in my JLabels?

BoxLayout 将遵守组件的最大尺寸(和最小尺寸)。

对于普通文本,最大尺寸将是组件的首选尺寸,因此粘合会按预期工作。

HTML 与常规文本的最大尺寸计算似乎有所不同。

I can get around this by specifying that the maximum size should be equal to the preferred size

是的,这是一种合理的方法,但我会覆盖 getMaximumSize() 方法以简单地 return getPreferredSize() 值。

@Override
public Dimension getMaximumSize()
{
    return getPreferredSize();
}

这样,如果您更改 HTML 它仍然有效。