java 如何右对齐 JLabel 中的图标?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2932389/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 23:31:05  来源:igfitidea点击:

How to right-justify icon in a JLabel?

javaswingjpaneljlabellayout-manager

提问by Geoffrey Zheng

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

对于带有图标的 JLabel,如果您使用setHorizontalTextPosition(SwingConstants.LEADING),则无论标签有多宽,图标都会在文本之后绘制。

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.

我跟踪了代码,似乎在 中SwingUtilities#layoutCompoundLabelImpl,文本宽度被简单地设置为SwingUtilities2.stringWidth(c, fm, text),并且图标 x 被设置为跟随文本而不考虑标签宽度。

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.

你可以看到标签总是填满框架,但图标保持不变。如果将两个参数都设置为 ,则会出现镜像问题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.

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

FYI this is jdk1.6.0_06 on Windows XP.

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

回答by axelrod

You should use:

你应该使用:

label1.setHorizontalTextPosition(SwingConstants.LEFT);

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

(Set the position of the text, relative to the icon)

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

回答by trashgod

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

回答by Fred Andrews

I found a much easier way to do this. I needed to have this kind of layout in a JTable, and did the right justification by getting the text width and then manually setting the width between the text and the icon. I subclassed a DefaultTableCellRenderer for my JTable

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

Works great!
And yes, for real code one should check that the text width is not bigger than the DESIREDWIDTH.

效果很好!
是的,对于真正的代码,应该检查文本宽度是否大于 DESIREDWIDTH。



For automatic right-alignment without a fixed width that works with columns of variable 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);
        }
    }