【问题标题】:How to right-justify icon in a JLabel?如何右对齐 JLabel 中的图标?
【发布时间】:2011-02-25 07:39:52
【问题描述】:

对于带有图标的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,则会出现镜像问题。

我知道我可以覆盖 UI,或者使用 JPanel 等。我只是想知道我是否在 JLabel 中遗漏了一些简单的东西。如果不是,它似乎是一个 Java 错误。

仅供参考,这是 Windows XP 上的 jdk1.6.0_06。

【问题讨论】:

    标签: java swing jpanel jlabel layout-manager


    【解决方案1】:

    这是想要的效果吗?

    附录:我认为面板是可行的方法。

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

    【讨论】:

    • 不,我需要让文本左对齐和图标右对齐。
    【解决方案2】:

    我找到了一种更简单的方法来做到这一点。我需要在 JTable 中进行这种布局,并通过获取文本宽度然后手动设置文本和图标之间的宽度来进行正确的调整。我为我的 JTable 子类化了一个 DefaultTableCellRenderer

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

    【讨论】:

    • 很好的解决方案。我冒昧地添加了一种适用于可变列宽的方法。
    【解决方案3】:

    你应该使用:

    label1.setHorizo​​ntalTextPosition(SwingConstants.LEFT);

    (设置文本的位置,相对于图标)

    【讨论】:

      猜你喜欢
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      • 2012-09-17
      • 2011-11-25
      • 2012-08-07
      • 1970-01-01
      • 1970-01-01
      • 2015-06-15
      相关资源
      最近更新 更多