8

是否有一种外观独立的方式来将组件(例如 a JLabel)与a的文本JCheckBox水平对齐?

我正在尝试使用 中的值UIDefaults来预测文本相对于JCheckBox. 我找到了一种组合,可以为 Metal、Windows、Motif 和 A​​qua 外观提供正确的结果:
示例:金属(正确对齐)

但不在 Nimbus 中:
示例:Nimbus(错误对齐)

是否有一种实用方法可以可靠地为所有外观中的文本提供 X、Y 偏移?


代码(注意:为避免任何布局副作用,我在此测试中使用了空布局):

import java.awt.Insets;

import javax.swing.JApplet;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.UIManager;
import javax.swing.border.Border;

public class AlignCheckBoxText extends JApplet {

    public AlignCheckBoxText() {
        setLayout(null);
        checkBox = new JCheckBox("Hello, World!");
        label = new JLabel("Hello, World!");
        add(checkBox);
        add(label);
    }

    @Override
    protected void validateTree() {
        checkBox.setLocation(0, 0);
        checkBox.setSize(checkBox.getPreferredSize());
        int labelX = UIManager.getIcon("CheckBox.icon").getIconWidth();
        Insets cbInsets = UIManager.getInsets("CheckBox.margin");
        if (cbInsets != null) labelX += cbInsets.left + cbInsets.right;
        Border cbBorder = UIManager.getBorder("CheckBox.border");
        if (cbBorder != null) {
            Insets borderInsets = cbBorder.getBorderInsets(checkBox);
            if (borderInsets != null) {
                labelX += borderInsets.left; 
            }
        }
        label.setLocation(labelX, checkBox.getHeight());
        label.setSize(label.getPreferredSize());
        super.validateTree();
    }

    private JCheckBox checkBox;
    private JLabel label;

}
4

4 回答 4

3

(致OP:请不要接受我之前的错误答案,我会删除它。对不起!)

您可以使用不为标签绘制复选框的复选框。这适用于 Windows JDK6 中的所有 LAF,包括 Nimbus。我没有mac,所以无法测试Aqua。

class CheckBoxLabel extends JCheckBox
{
    public CheckBoxLabel(String string)
    {
        super(string);
    }

    public void updateUI()
    {
        setUI(new CheckBoxLabelUI());
    }
}

class CheckBoxLabelUI extends BasicCheckBoxUI
{
    public void installUI(JComponent c)
    {
        super.installUI(c);
        Icon i = super.getDefaultIcon();
        icon_ = new EmptyIcon(i.getIconWidth(), i.getIconHeight());
    }

    public Icon getDefaultIcon()
    {
        return icon_;
    }

    private Icon icon_;
}

class EmptyIcon implements Icon
{
    public EmptyIcon()
    {
        this(0, 0);
    }

    public EmptyIcon(int width, int height)
    {
        width_ = width;
        height_ = height;
    }

    public int getIconHeight()
    {
        return height_;
    }

    public int getIconWidth()
    {
        return width_;
    }

    public void paintIcon(Component c, Graphics g, int x, int y)
    {
    }

    private int width_;
    private int height_;
}
于 2010-09-20T16:24:22.510 回答
2

您可以右对齐标签并将其宽度设置为复选框的宽度减去右边框。它适用于所有使用 Windows JDK1.6.0_21 的 LAF,包括 Nimbus。我没有 Mac,所以无法测试 Aqua。

这是您的代码稍作修改:

class AlignCheckBoxText extends JApplet {

    public AlignCheckBoxText() {
        setLayout(null);
        checkBox = new JCheckBox("Hello, World!");
        label = new JLabel("Hello, World!");
        add(checkBox);
        add(label);        
        label.setHorizontalAlignment(JLabel.TRAILING);
    }

    @Override
    protected void validateTree() {
        checkBox.setLocation(0, 0);
        checkBox.setSize(checkBox.getPreferredSize());
        int x = 0;
        Border cbBorder = UIManager.getBorder("CheckBox.border");
        if (cbBorder != null) {
            Insets borderInsets = cbBorder.getBorderInsets(checkBox);
            if (borderInsets != null) {
                x += borderInsets.right;
            }
        }
        label.setLocation(0, checkBox.getHeight());
        label.setSize(new Dimension(checkBox.getPreferredSize().width - x, label.getPreferredSize().height));
        super.validateTree();
    }

    private JCheckBox checkBox;
    private JLabel label;

}
于 2010-09-18T21:49:50.067 回答
1

这不是一个完整的回复,但它可能会对您有所帮助:

如果添加checkBox.getIconTextGap()到 labelX 的值,则 Nimbus 的对齐似乎可以,但对于 metal 或 GTK 则不行。

于 2010-09-18T16:25:39.443 回答
1

如果您使用 GroupLayout,Netbeans GUI 构建器可以将复选框的文本和下一行的标签对齐.... 有点。

它似乎适用于 Nimbus,但在另一个 LAF 中,标签文本离右侧太远了一个像素。查看 GUI 构建器中为 GroupLayout 生成的代码,它在标签前面留出了 22x22 的间隙。对于 Nimbus,22 似乎是正确的,但对于其他 LAF,它似乎是 21。

生成的代码如下所示。

GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHortizontalGroup(
  layout.createParallelGroup(Alignment.LEADING)
    .addGroup(layout.createSequentialGroup()
      .addContainerGap()
      .addGroup(layout.createParallelGroup(Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
          .addGap(22,22,22)
          .addComponent(label)
        )
        .addComponent(checkBox)
      )
    )
);

layout.setVerticalGroup(
  layout.createParallelGroup(Alignment.LEADING)
    .addGroup(layout.createSequentialGroup()
      .addContainerGap()
      .addComponent(checkBox)
      .addPreferredGap(ComponentPlacement.RELATED)
      .addComponent(label)
    )
);

此代码将在标签和复选框的分配之后进入示例类的构造函数。另外,删除 setLayout(null);

综上所述,根据我使用 GUI 构建器所看到的情况,我会推荐以下内容:

  1. Border cbBorder从样品中取出钻头
  2. 添加checkBox.getIconTextGap()到 labelX。
  3. 如果 LAF 是 nimbus,则将 4 添加到 labelX。:)
于 2010-09-18T19:30:40.340 回答