2010-09-18 27 views
7

¿Hay un look-and-feel-independiente manera de alinear un componente (por ejemplo, un JLabel) horizontalmente con el texto de un JCheckBox?alinear un JLabel con el texto de una JCheckBox

Estoy tratando de usar valores del UIDefaults para predecir la ubicación del texto relativo a la esquina superior izquierda de JCheckBox. He encontrado una combinación que da el resultado correcto para el metal, Windows, Motif y Aqua Mira-y-siente:
Example: Metal (correctly-aligned)

Pero no en Nimbus:
Example: Nimbus (incorrectly-aligned)

¿Existe un método de utilidad alguna parte ¿Eso le dará confiablemente compensaciones X, Y para el texto en todos los Look-and-Feels?


Código (nota: para evitar cualquier diseño de efectos secundarios que utiliza un diseño nulo para esta prueba):

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

En este caso, sería más simple crear una casilla de verificación sin texto, y una JLabel separada que contiene el texto de la casilla de verificación original. – barjak

+0

@barjak, que interferirá con la visualización del enfoque. Normalmente, hay un borde alrededor de la casilla de verificación (icono y texto) para mostrar cuándo está enfocado. Al hacer clic en el texto, ya no se activará la selección de la casilla de verificación. – finnw

Respuesta

3

(Para OP: por favor, inaceptables desde mi anterior respuesta equivocada, y lo borraré este momento.!)

Puede usar una casilla de verificación que no pinta la casilla de verificación para sus etiquetas. Esto funciona para todas las LAF en Windows JDK6, incluido Nimbus. No tengo un Mac así que no puedo probar 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

Ésta no es una respuesta completa, pero podría ayudarle a:

Si agrega checkBox.getIconTextGap() al valor de la etiqueta X, la alineación parece estar bien con Nimbus, pero no está bien con metal o GTK.

+0

Interesante. 'checkBox.getIconTextGap' da un resultado útil (posiblemente una coincidencia) en Nimbus pero un resultado no útil en otros L & Fs. 'UIManager.getInt (" CheckBox.textIconGap ")' siempre devuelve cero. – finnw

+0

Esta fue la solución que iba a sugerir también, aunque debe tener en cuenta que las LAF no están obligadas a utilizar ninguno de los valores predeterminados de UIManager. También obtengo un valor distinto de cero para las LAF predeterminadas. Consulte el programa Predeterminado de UIManager (http://tips4java.wordpress.com/2008/10/09/uimanager-defaults/). Todos los ejemplos que he visto en el tutorial Swing anulan el método init() para crear la GUI. Tal vez el problema es con el método que está anulando y el LAF aún no está instalado. Pruebe de la manera normal o intente crear un JFrame para su demostración para ver si hay alguna diferencia. – camickr

1

Si usa GroupLayout, el generador de la interfaz gráfica de usuario de Netbeans puede alinear el texto de una casilla de verificación y una etiqueta en la línea siguiente ... más o menos.

Parece que funciona bien para Nimbus, pero en el otro LAF, el texto de la etiqueta está un píxel demasiado a la derecha. Al observar el código generado para GroupLayout en el constructor de la GUI, se abre un espacio de 22x22 frente a la etiqueta. Para Nimbus, 22 parece correcto, pero para las otras LAF parece ser 21.

El código generado tiene este aspecto.

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

Este código iría en el constructor de la clase de muestra después de las asignaciones de etiqueta y casilla de verificación. Además, elimine setLayout (null);

Todo esto se dice, sobre la base de lo que he visto usando el constructor de interfaz gráfica de usuario, le recomiendo la siguiente verdad:

  1. quitar el bit Border cbBorder de la muestra
  2. añadir el checkBox.getIconTextGap() a la etiquetaX.
  3. Si el LAF es nimbo, agregue 4 a labelX. :)
2

Puede alinear a la derecha la etiqueta y configurar su ancho para que sea el ancho de la casilla de verificación menos el borde derecho. Funciona para todas las LAF con Windows JDK1.6.0_21, incluido Nimbus. No tengo una Mac así que no puedo probar Aqua.

Aquí está tu código muy ligeramente modificado:

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

Desearía poder eliminar o rechazar mi respuesta. En realidad es muerte cerebral (sin ofender a OP, es todo culpa mía). Solo funciona cuando la casilla de verificación y la etiqueta tienen texto idéntico. Podrías hackearlo configurando el verdadero texto de la casilla de verificación después de configurar el tamaño de la etiqueta, pero luego tendrías que hacer eso siempre que cambie el texto de la etiqueta. También falla para la configuración regional de derecha a izquierda. Una respuesta real probablemente necesite profundizar en la interfaz de usuario de la casilla de verificación, con la que no estoy familiarizado. Lo siento. –

+0

Aunque esta respuesta tiene inconvenientes, creo que esto debería permanecer. No lo borres Aunque tal vez el OP podría no aceptarlo. –