2010-09-18 49 views
7

的文本的JLabel是否有外观和感觉无关对准组件的方式(例如JLabel)水平与JCheckBox文本对准一个JCheckBox的

我正在尝试使用UIDefaults中的值来预测文本相对于JCheckBox左上角的位置。我发现了一个的组合,让正确的结果对于金属的Windows,Motif和水族的外观和感觉:
Example: Metal (correctly-aligned)

但不是在雨云:
Example: Nimbus (incorrectly-aligned)

是有一个实用的方法某处那将可靠地为所有外观的文本提供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; 

} 
+1

在这种情况下,创建一个没有文本的复选框以及包含原始复选框文本的单独JLabel会更简单。 – barjak 2010-09-18 14:15:23

+0

@barjak,这将与焦点显示混乱。通常在复选框(图标和文本)周围有一个边框,以显示它的焦点时间。同时点击文本将不再切换复选框选择。 – finnw 2010-09-18 14:28:35

回答

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_; 
} 
1

这是不是一个完整的响应,但它可以帮助你:

如果您将checkBox.getIconTextGap()添加到labelX的值,则Nimbus的对齐方式似乎正常,但对于金属或GTK,对齐似乎没有问题。

+0

有趣。 'checkBox.getIconTextGap'在Nimbus中给出了一个有用的结果(可能是巧合),但是在其他L&F中却是一个无用的结果。 'UIManager.getInt(“CheckBox.textIconGap”)'总是返回零。 – finnw 2010-09-18 16:47:14

+0

这也是我将要建议的解决方案,但您应该注意,LAF不会被迫使用任何UIManager默认值。此外,我确实得到了默认LAF的非零值。查看UIManager默认程序(http://tips4java.wordpress.com/2008/10/09/uimanager-defaults/)。我在Swing教程中见过的所有示例都会覆盖用于创建GUI的init()方法。也许问题在于你正在重写的方法,并且LAF尚未安装?尝试正常的方法或尝试为您创建一个JFrame演示,看看是否有区别。 – camickr 2010-09-19 02:06:17

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) 
    ) 
); 

此代码将在标签和checkBox的赋值之后进入示例类的构造函数中。另外,删除setLayout(null);

所有这一切都被说,根据我所使用的GUI构建器看到的,我建议你真正执行以下操作:

  1. 从样品取出Border cbBorder
  2. 添加checkBox.getIconTextGap()到标签X。
  3. 如果LAF是灵气,则将4添加到labelX。 :)
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; 

} 
+1

我希望我可以删除或投票我的答案。这真的是脑死亡(OP没有进攻,这都是我的错)。它只有在复选框和标签具有相同的文本时才起作用。你可以通过在设置标签大小后设置真正的复选框文本来破解它,但是只要标签文本发生更改,就必须这样做。它也从右到左的区域设置失败。真正的答案可能需要深入研究复选框UI,这是我不熟悉的。抱歉。 – 2010-09-20 03:22:55

+0

即使这个答案有缺点,我认为这应该留下来。不要删除它。尽管OP可能不接受它。 – 2010-09-20 17:03:27