2010-05-28 5 views
9

Pour un JLabel avec icône, si vous setHorizontalTextPosition(SwingConstants.LEADING), l'icône est peinte juste après le texte, quelle que soit la largeur de l'étiquette.Comment justifier une icône à droite dans un JLabel?

Ceci est particulièrement mauvais pour une liste, car les icônes seraient partout en fonction de la longueur du texte pour chaque élément.

J'ai tracé le code et il semble que dans SwingUtilities#layoutCompoundLabelImpl, la largeur du texte est simplement définie sur SwingUtilities2.stringWidth(c, fm, text), et l'icône x est définie pour suivre le texte sans tenir compte de la largeur de l'étiquette.

Voici cas le plus 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); 
      } 
     }); 
    } 
} 

Vous pouvez voir que l'étiquette remplit toujours le cadre, mais l'icône reste en place. Vous obtiendrez le problème de miroir si vous définissez les deux arguments à TRAILING. Je sais que je peux remplacer l'interface utilisateur, ou utiliser un JPanel, etc. Je me demande simplement s'il me manque quelque chose de simple dans JLabel. Sinon, cela ressemble à un bug Java.

FYI c'est jdk1.6.0_06 sur Windows XP.

Répondre

12

Est-ce l'effet souhaité?

Addendum: Je pense qu'un panneau est la voie à suivre.

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, je dois avoir du texte justifié à gauche et l'icône justifié à droite. –

+0

Ah, je vois ce que tu veux dire. – trashgod

20

Vous devez utiliser:

label1.setHorizontalTextPosition (SwingConstants.LEFT);

(Définir la position du texte, par rapport à l'icône)

5

J'ai trouvé un moyen beaucoup plus facile de le faire. J'avais besoin d'avoir ce type de mise en page dans un JTable, et j'ai fait la bonne justification en obtenant la largeur du texte, puis en définissant manuellement la largeur entre le texte et l'icône. J'ai sous-classé un DefaultTableCellRenderer pour mon 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); 
     ... 
    } 
} 

Fonctionne bien!
Et oui, pour le vrai code, il faut vérifier que la largeur du texte n'est pas plus grande que le DÉSIRABLE.


Pour le bon alignement automatique sans une largeur fixe qui fonctionne avec des colonnes de largeur 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

Bonne solution. J'ai pris la liberté d'ajouter une méthode qui fonctionne avec des largeurs de colonnes variables. –

Questions connexes