2010-09-18 46 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