Search code examples
javaswingjpaneljlabellayout-manager

How to right-justify icon in a JLabel?


For a JLabel with icon, if you setHorizontalTextPosition(SwingConstants.LEADING), the icon is painted right after text, no matter how wide the label is.

This is particularly bad for a list, as the icons would be all over the place depending on how long the text is for each item.

I traced the code and it seems to be that in SwingUtilities#layoutCompoundLabelImpl, text width is simply set to SwingUtilities2.stringWidth(c, fm, text), and icon x is set to follow text without considering label width.

Here is the simplest case:

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

You can see that label always fills the frame but icon stays put. You'll get the mirror problem if you set both arguments to TRAILING.

I know I can override the UI, or use a JPanel, etc. I just wonder if I'm missing something simple in JLabel. If not, it seems like a Java bug.

FYI this is jdk1.6.0_06 on Windows XP.


Solution

  • Is this the desired effect?

    Addendum: I think a panel is the way to go.

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