2010-09-18 12 views
7

Czy istnieje look-and-feel-niezależny sposób, aby wyrównać komponent (np JLabel) poziomo z tekstem z JCheckBox?Wyrównaj do JLabel z tekstem o JCheckBox

Próbuję użyć wartości z UIDefaults, aby przewidzieć położenie tekstu względem lewego górnego rogu JCheckBox. Znalazłem kombinację, która daje prawo wynik na metal, Windows, Motif i wygląd aqua-i-Temp:
Example: Metal (correctly-aligned)

Ale nie w Nimbus:
Example: Nimbus (incorrectly-aligned)

Czy istnieje metoda narzędzie gdzieś który w niezawodny sposób zapewni przesunięcia X, Y dla tekstu we wszystkich Look-and-Feels?


Code (uwaga: aby uniknąć układu uboczne użyłem null układ dla tego testu):

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

W tym przypadku byłoby prostsze, aby utworzyć pole bez tekstu, a oddzielny JLabel, który zawiera tekst oryginalnego pole wyboru jest. – barjak

+0

@barjak, który będzie bałagan z wyświetlaniem ostrości. Zwykle wokół pola wyboru znajduje się obramowanie (ikona i tekst), aby pokazać, kiedy jest ono skupione. Kliknięcie tekstu nie będzie już przełączać wyboru pola wyboru. – finnw

Odpowiedz

3

(OP: proszę unaccept moją wcześniejszą błędną odpowiedź, a ja go usunąć Przepraszam.!)

Możesz użyć pola wyboru, które nie powoduje zaznaczenia pola wyboru dla etykiet. Działa to dla wszystkich LAF w Windows JDK6, w tym Nimbus. Nie mam mac, więc nie mogę przetestować 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

To nie jest pełna odpowiedź, ale może pomóc:

Jeśli dodasz checkBox.getIconTextGap() do wartości etykiety X, wyrównanie wydaje się być w porządku z Nimbus, ale nie jest w porządku z metalem lub GTK.

+0

Interesujące. 'checkBox.getIconTextGap' daje użyteczny wynik (prawdopodobnie koincydencję) w Nimbusie, ale nieużyteczny wynik w innych L & F. 'UIManager.getInt (" CheckBox.textIconGap ")' zawsze zwraca zero. – finnw

+0

To było rozwiązanie, które zamierzałem zasugerować, chociaż należy pamiętać, że LAF nie są zmuszane do używania żadnej z wartości domyślnych UIManager. Dostaję również niezerową wartość dla domyślnych LAF. Sprawdź program UIManager Defaults (http://tips4java.wordpress.com/2008/10/09/uimanager-defaults/). Wszystkie przykłady, które widziałem w samouczku Swinga, zastępują metodę init() w celu utworzenia GUI. Może problem polega na tym, że metoda jest nadrzędna, a LAF nie jest jeszcze zainstalowany? Spróbuj normalnie lub spróbuj utworzyć demo JFrame, aby zobaczyć, czy istnieje różnica. – camickr

1

Jeśli używasz GroupLayout, program budujący GUI Netbeans może wyrównać tekst pola wyboru i etykiety w następnym wierszu .... sort.

Wygląda na to, że działa dobrze dla Nimbus, ale w drugim LAF tekst etykiety jest o jeden piksel za daleko z prawej strony. Patrząc na wygenerowany kod dla GroupLayout w konstruktorze GUI, tworzy on lukę 22x22 przed etykietą. Dla Nimbus 22 wydaje się słuszne, ale dla innych LAF wydaje się być 21.

Wygenerowany kod wygląda następująco.

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

Ten kod zostanie umieszczony w konstruktorze klasy próbki po przypisaniu etykiety i pola wyboru. Usuń także setLayout (null);

Wszystko to na uwadze powyższe, na podstawie tego co widziałem przy użyciu GUI Builder, polecam następujące za prawdziwe:

  1. usunąć Border cbBorder trochę z próbki
  2. dodać checkBox.getIconTextGap() do labelX.
  3. Jeśli LAF jest nimbus, dodaj 4 do labelX. :)
2

Można wyrównać etykietę w prawo i ustawić jej szerokość tak, aby była szerokość pola wyboru minus prawa krawędź. Działa dla wszystkich LAF z Windows JDK1.6.0_21, w tym Nimbus. Nie mam komputera Mac, więc nie mogę przetestować Aqua.

Oto kod bardzo nieznacznie modyfikowany:

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

Chciałbym móc skasować lub cofnąć swoją odpowiedź. To naprawdę martwy mózg (bez obrazy OP, to wszystko moja wina). Działa tylko wtedy, gdy pole wyboru i etykieta mają identyczny tekst. Możesz go zhackować, ustawiając tekst w rzeczywistym polu wyboru po ustawieniu rozmiaru etykiety, ale musisz to zrobić, gdy tylko zmieni się tekst etykiety. Nie działa także z ustawieniami od prawej do lewej. Prawdziwa odpowiedź prawdopodobnie musiałaby zagłębić się w pole wyboru, którego nie znam. Przepraszam. –

+0

Mimo że ta odpowiedź ma wady, myślę, że to powinno pozostać. Nie usuwaj go. Chociaż być może PO nie może tego zaakceptować. –