2010-05-28 17 views
9

Para un JLabel con ícono, si setHorizontalTextPosition(SwingConstants.LEADING), el ícono se pinta justo después del texto, sin importar qué tan ancha sea la etiqueta.¿Cómo justificar correctamente el icono en un JLabel?

Esto es especialmente malo para una lista, ya que los iconos estarían por todas partes dependiendo de cuánto tiempo el texto es para cada elemento.

He rastreado el código y parece ser que en SwingUtilities#layoutCompoundLabelImpl, el ancho del texto simplemente se establece en SwingUtilities2.stringWidth(c, fm, text), y el icono x está configurado para seguir el texto sin tener en cuenta el ancho de la etiqueta.

Aquí es el caso más simple:

import java.awt.*; 
import javax.swing.*; 

public class TestJLabelIcon 
{ 
    public static void main(String args[]) 
    { 
     EventQueue.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       JLabel c = new JLabel("abc"); 
       c.setHorizontalTextPosition(SwingConstants.LEADING); 
       c.setHorizontalAlignment(SwingConstants.LEADING); 
       c.setIcon(UIManager.getIcon("FileChooser.detailsViewIcon")); 
       c.setBorder(BorderFactory.createLineBorder(Color.RED)); 

       JFrame frame = new JFrame(); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.getContentPane().add(c);  
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 

se puede ver que la etiqueta siempre se llena el cuadro, pero el icono permanece fija. Obtendrá el problema de espejo si establece ambos argumentos en TRAILING.

Sé que puedo anular la interfaz de usuario, o usar un JPanel, etc. Me pregunto si me está perdiendo algo simple en JLabel. Si no, parece un error de Java.

FYI esto es jdk1.6.0_06 en Windows XP.

Respuesta

12

¿Es este el efecto deseado?

Adición: Creo que un panel es el camino a seguir.

image

import java.awt.*; 
import javax.swing.*; 

public class TestJLabelIcon { 

    public static void main(String args[]) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       JFrame frame = new JFrame(); 
       frame.setLayout(new GridLayout(0, 1)); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(createPanel("abc")); 
       frame.add(createPanel("defghij")); 
       frame.add(createPanel("klmn")); 
       frame.add(createPanel("opq")); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 

      private JPanel createPanel(String s) { 
       JPanel p = new JPanel(new BorderLayout()); 
       p.add(new JLabel(s, JLabel.LEFT), BorderLayout.WEST); 
       Icon icon = UIManager.getIcon("FileChooser.detailsViewIcon"); 
       p.add(new JLabel(icon, JLabel.RIGHT), BorderLayout.EAST); 
       p.setBorder(BorderFactory.createLineBorder(Color.blue)); 
       return p; 
      } 
     }); 
    } 
} 
+0

Nop, tengo que tener el texto justificado a la izquierda y el icono justificado a la derecha. –

+0

Ah, entiendo a qué te refieres. – trashgod

20

Deberá utilizar:

label1.setHorizontalTextPosition (SwingConstants.LEFT);

(Ajuste la posición del texto, en relación con el icono)

5

he encontrado una manera mucho más fácil de hacer esto. Necesitaba tener este tipo de diseño en una JTable e hice la justificación correcta al obtener el ancho del texto y luego establecer manualmente el ancho entre el texto y el ícono. Subclassed un DefaultTableCellRenderer para mi JTable

public class FixedWidthRenderer extends DefaultTableCellRenderer 
{ 
    ... 
    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, 
     boolean isSelected, boolean hasFocus, int row, int column) 
    { 
     ... 
     FontMetrics met = super.getFontMetrics(super.getFont()); 
     int width = met.stringWidth(super.getText());     
     super.setIconTextGap(DESIREDWIDTH - width); 
     ... 
    } 
} 

Funciona muy bien!
Y sí, para el código real, uno debe verificar que el ancho del texto no sea mayor que el DESIREDWIDTH.


Por derecho alineación automática y sin un ancho fijo que funciona con columnas de ancho variable:

@Override 
    public void setBounds(int x, int y, int width, int height) { 
     super.setBounds(x, y, width, height); 
     if (getIcon() != null) { 
      int textWidth = getFontMetrics(getFont()).stringWidth(getText()); 
      Insets insets = getInsets(); 
      int iconTextGap = width - textWidth - getIcon().getIconWidth() - insets.left - insets.right - PADDING; 
      setIconTextGap(iconTextGap); 
     } else { 
      setIconTextGap(0); 
     } 
    } 
+0

Buena solución. Me tomé la libertad de agregar un método que funciona con anchos de columna variables. –