代码之家  ›  专栏  ›  技术社区  ›  Geoffrey Zheng

如何右对齐jLabel中的图标?

  •  9
  • Geoffrey Zheng  · 技术社区  · 16 年前

    对于带有图标的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。

    3 回复  |  直到 8 年前
        1
  •  13
  •   trashgod    8 年前

    这是预期效果吗?

    附录:我认为一个小组就是解决问题的方法。

    >代码>导入Java.AWT.*; 导入javax.swing.*; 公共类testjLabelIcon{ 公共静态void main(字符串args[]){ eventQueue.invokelater(new runnable()){ @重写 public void run()。{ jframe frame=new jframe(); frame.setlayout(新网格布局(0,1)); frame.setDefaultCloseOperation(jframe.exit在关闭时退出); frame.add(创建面板(“abc”)); frame.add(createpanel(“defghij”)); frame.add(createpanel(“klmn”)); frame.add(createpanel(“opq”)); 帧(); frame.setLocationRelativeTo(空); frame.setVisible(真); } private jpanel createpanel(字符串s){ jpanel p=新jpanel(new borderlayout()); p.add(新jlabel(s,jlabel.left),borderlayout.west); icon icon=uimanager.geticon(“filechooser.detailsviewicon”); p.add(新jlabel(icon,jlabel.right),borderlayout.east); p.setborder(borderFactory.createlineborder(color.blue)); 返回P; } (}); } } < /代码> 一个小组就是解决问题的方法。

    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;
                }
            });
        }
    }
    
        2
  •  21
  •   axelrod    13 年前

    你应该使用:

    label1.setHorizontalExtPosition(swingConstants.Left);

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

        3
  •  6
  •   Ingo Kegel    11 年前

    我找到了一个更简单的方法。我需要在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); 
            ...
        }
    }
    

    工作很棒!
    是的,对于真正的代码,应该检查文本宽度是否不大于期望的宽度。


    对于不使用固定宽度的自动右对齐,该宽度适用于可变宽度的列:

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