【问题标题】:Multi-colored JLabel多色 JLabel
【发布时间】:2017-10-04 17:58:33
【问题描述】:

我想要一种不同的方式来创建多色 JLabel。 (多色 = 不同前景色的部分文本)

到目前为止,我发现的唯一解决方案(也是我目前使用的)是在 html 中设置文本。但是我遇到了问题......

当 LayoutManager 决定 JLabel 应该缩小,在 JLabel 中使用纯文本时,文本会被裁剪,并添加“...”。 (例如:“My Long Text” -> 变为:“My Long T...”)

在 JLabel 中使用 html 时,文本会包裹在空格字符的某处,而其余部分则留在可绘制区域之外,并且由于 JLabel 的高度不变,因此不可见。 (例如:“My Long Text” -> 变为:“My Long”)

在我的例子中,JLabel 是在 JTable 中呈现的,它可以由用户调整大小,更不用说在不同的屏幕分辨率下。

我尝试在 html 中添加“nowrap”属性或“”标签,但看起来这被忽略了。

留给我 - 我认为 - 一个解决方案:我自己绘制标签。 或不? 有什么建议么? 例子?

谢谢。

这是一个非常简单的例子: 尝试水平调整此面板的大小,看看两个 JLabel 中的文本会发生什么...

(没有提示用户,第二个JLabel的文本不是完整的内容)

-> 在示例中,JLabel 的高度发生了变化,但是当在框架的 JTable 中呈现时,行的高度没有改变,我不希望它改变。如果不使用 HTML,它也不会改变高度...

import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; public class MultiJLabel extends JFrame { public MultiJLabel() { super("Multi-colored JLabel test"); JPanel pnl = new JPanel(); pnl.setLayout(new BorderLayout()); pnl.add(new JLabel("This is a test of My Long Text"), BorderLayout.NORTH); pnl.add(new JLabel("<html>This is a test of <font color='#ffbebe'>My Long Text</font></html>"), BorderLayout.SOUTH); this.getContentPane().add(pnl); this.pack(); this.setDefaultCloseOperation(EXIT_ON_CLOSE); this.setVisible(true); } public static void main(String[] args) { new MultiJLabel(); } }

Here's a picture of the original problem, where our users are not aware that the client's Order Number is not what the grid is showing, because this column has HTML-formatted text to show multi-colors.

【问题讨论】:

  • 你能显示minimal reproducible example。 HTML 无疑是最简单的。在这里,您的问题与多色无关,而是与包装文本有关。首先,如果你的文字太长,你会期待什么?
  • @all 我投票支持重新打开,副本是关于 JLabelJList 内,这与在相同 JLabel 内具有不同颜色不同。请注意,这里有一个隐藏的问题,“如果 HTML 是一种解决方案,如何使 wrap 正常工作?”。
  • @AxelH 感谢您的快速回复。我用一个最小的例子编辑了我最初的问题(因为最初的问题发生在一个大框架内)。我期望的是某种指示,告诉用户显示的文本不完整。

标签: java swing


【解决方案1】:

感谢大家的cmets,但我不耐烦并创建了自己的JLabel。 我知道它可能是一个糟糕的编程版本,但它对我有用...... 你可以通过改变上面的例子来测试它:

JMultiColorLabel lbl = new JMultiColorLabel("This is a test of My Long Text");
lbl.setColors(new int[]{10,15}, new Color[]{Color.RED,Color.BLUE});
lbl.setPreferredSize(new Dimension(200,20));
pnl.add(lbl, BorderLayout.SOUTH);

并使用这个类:

import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.util.HashMap;

import javax.swing.JLabel;

public class JMultiColorLabel
    extends JLabel
    {
    private static final String             STRING_OVERFLOW     = "...";

    private HashMap<Integer, Color>     extraColors             = new HashMap<Integer, Color>();

    public JMultiColorLabel(String text)
        {
        super(text);
        }

    public void setColors(int[] indices, Color[] colors)
        {
        for (int i = 0; i < indices.length; i++)
            this.extraColors.put(indices[i], colors[i]);
        }

    protected void paintComponent(Graphics g)
        {
        // Get text-contents of Label
        String text = this.getText();

        // No text in the JLabel? -> No risk: super
        if (text == null || text.length() == 0)
            {
            super.paintComponent(g);
            return;
            }

        // Content Array of characters to paint
        char[] chars = text.toCharArray();

        // Draw nice and smooth
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

         // Draw background
        if (this.isOpaque())
          {
          g2d.setColor(this.getBackground());
          g2d.fillRect(0, 0, this.getWidth(), this.getHeight());
          }

        // FontMetrics to calculate widths and height
        FontMetrics fm = g2d.getFontMetrics();

        // Available space
        Insets ins = this.getInsets();
        int maxSpace = this.getWidth()-(ins.left+ins.right);
        boolean overflow = (fm.stringWidth(text) > maxSpace);

        // Starting offset
        int offset = ins.left+1;

        // The start Color is the default
        g2d.setColor(this.getForeground());

        // Loop over characters
        for (int i = 0; i < chars.length; i++)
            {
                // Switch Color?
            if (this.extraColors.containsKey(i))
                g2d.setColor(this.extraColors.get(i));

                // Check if we still have enough room for this character
            if (overflow && offset >= (maxSpace-fm.stringWidth(STRING_OVERFLOW)))
                { // Draw overflow and stop painting
                g2d.drawString(STRING_OVERFLOW, offset, (fm.getHeight()+ins.top));
                return;
                }
            else // We have the space -> Draw the character
                g2d.drawString(String.valueOf(chars[i]), offset, (fm.getHeight()+ins.top));

                // Move cursor to the next horizontal position
            offset += fm.charWidth(chars[i]);
            }
        }
    }

【讨论】:

    【解决方案2】:

    为防止在 JLabels 中使用 html-text 时换行,请将文本换行在 nobr(无中断)标签中:

    new JLabel("<html><nobr>This is a test of <font color='#ffbebe'>My Long Text</font></nobr></html>")
    

    当使用nobr-标签时,该行不会被换行,但也不会被截断。因此,显示文本的末尾不会有任何省略号 (...),但它会被截断。

    缺少的... 实际上可能在表格中具有优势,因为省略号不会丢失额外的宽度,因此会显示更多内容。但对于用户来说,没有它们的内容可能就不那么明显了。

    【讨论】:

    • 当无法显示所有内容时,您应该让工具提示显示单元格的完整内容,我认为...最好知道是否全部显示
    猜你喜欢
    • 2013-03-30
    • 1970-01-01
    • 2014-08-03
    • 2012-12-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多