Как правильно выровнять значок в JLabel? - PullRequest
9 голосов
/ 29 мая 2010

Для JLabel со значком, если вы setHorizontalTextPosition(SwingConstants.LEADING), значок окрашивается сразу после текста, независимо от ширины ярлыка.

Это особенно плохо для списка, так как значки будут повсюду, в зависимости от длины текста для каждого элемента.

Я проследил код, и похоже, что в SwingUtilities#layoutCompoundLabelImpl ширина текста просто установлена ​​на SwingUtilities2.stringWidth(c, fm, text), а значок x установлен так, чтобы следовать за текстом без учета ширины метки.

Вот самый простой случай:

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

Вы можете видеть, что метка всегда заполняет рамку, но значок остается на месте. Вы получите проблему с зеркалом, если вы установите оба аргумента на TRAILING.

Я знаю, что могу переопределить пользовательский интерфейс или использовать JPanel и т. Д. Мне просто интересно, упустил ли я что-то простое в JLabel. Если нет, то это похоже на ошибку Java.

К вашему сведению, это jdk1.6.0_06 в Windows XP.

Ответы [ 3 ]

21 голосов
/ 28 августа 2012

Вы должны использовать:

label1.setHorizontalTextPosition (SwingConstants.LEFT);

(установить положение текста относительно иконки)

13 голосов
/ 29 мая 2010

Это желаемый эффект?

Приложение: я думаю, что панель - это путь.

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;
            }
        });
    }
}
6 голосов
/ 20 августа 2014

Я нашел гораздо более простой способ сделать это. Мне нужно было иметь такую ​​компоновку в JTable, и я сделал правильное выравнивание, получив ширину текста и затем вручную установив ширину между текстом и значком. Я вложил в класс DefaultTableCellRenderer для 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); 
        ...
    }
}

Отлично работает!
И да, для реального кода нужно проверить, что ширина текста не больше, чем DESIREDWIDTH.


Для автоматического выравнивания по правому краю без фиксированной ширины, который работает со столбцами переменной ширины:

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