如何突出JLabel的一部分?

时间:2010-08-20 18:53:38

标签: java swing jtable jlabel

在任何人建议HTML之前,我稍后会解释为什么这不是一个选项。我有一个表,其中包含一个包含文本单元格的列。我需要能够突出显示每个单元格中的一些文本。因此,例如,如果单元格包含“cat foo dog”......我可能想要突出显示foo。

我当前的方法是使用一个自定义的TableCellRenderer,它将html放入一个呈现的JLabel组件中,并且暂时很好。然后我注意到,当单元格中的文本变得太长而无法适应列宽时,它只是截断了文本而没有在这种情况下正常发生的正常“...”。因此,用户不知道他们没有看到更多的文字。另一个问题是,如果原始文本本身包含HTML,在我的情况下它有时会执行,则单元格将无法正确呈现。我知道我可以逃脱html,但我仍然会遇到流行的问题。

如果我使用jlabel以外的组件,那么它会让我的桌子看起来很奇怪。有没有人有什么建议?感谢

3 个答案:

答案 0 :(得分:7)

嗯,这是一个解决方案。

简而言之,您可以将JLabel子类化为手动绘制突出显示。覆盖paintComponent方法以进行实际绘制,并使用FontMetrics计算应在何处绘制突出显示的区域。

以下是令人难以忍受的细节答案:

基本上,您可以创建一个可以突出显示内容的JLabel的子类。我愿意这样做;你可能想要有所不同:

添加一个方法,告诉标签要突出显示哪个部分。这可能是这样的,假设您只需要一个突出显示的区域:

public void highlightRegion(int start, int end) {
     // Set some field to tell you where the highlight starts and ends...
}

如果你需要多个区域,只需要一个ArrayList而不是一个简单的字段。取消照明的方法也可能有用。

现在,您需要覆盖paintComponent的{​​{1}}方法。在这里,您需要执行几个不同的步骤,您可能希望以不同的方法或其他方式组织这些步骤。为简单起见,我将把它全部放在paint方法中。

JLabel

首先,你需要弄清楚突出显示的物理尺寸,你可以使用漂亮的@Override protected void paintComponent(Graphics g) { ... 类来做。为您正在使用的FontMetrics创建FontMetrics课程。

Font

现在,您可以获得创建将成为亮点的矩形所需的所有信息。你需要起始位置,高度和宽度。为此,您需要 FontMetrics metrics = new FontMetrics(getFont()); 文本的两个子字符串,如下所示:

JLabel

现在,您可以在绘制标签的其余部分之前绘制突出显示的区域:

  String start = getText().substring(0, startOfHighlight);
  String text = getText().substring(startOfHighlight, endOfHighlight);
  //You may also need to account for some offsets here:
  int startX = metrics.stringWidth(start);
  int startY = 0; //You probably have some vertical offset to add here.
  int length = metrics.stringWidth(text);
  int height = metrics.getHeight();

当然,如果您希望突出显示跨越多行,则需要更多工作。

如果你想知道,我之前已经写过这样的东西了。一时兴起,我决定从 g.fillRect(startX, startY, length, height); super.paintComponent(g); } 编写自己的文本区域类型组件,这基本上就是我处理突出显示的方式。在实际项目中重新发明轮子可能是愚蠢的,但它确实会教你随机的东西可能会有用......

答案 1 :(得分:2)

这是一个很好的答案,也许是最好的解决方案。但有些人可能会觉得更简单的替代方法是使用JTextfield而不是JLabel进行渲染,然后可以使用JTextfields突出显示功能,即

void highlightWhitespaceText(JTextField text)
    {
        text.setHighlighter(AbstractTableCellRenderer.defaultHighlighter);
        try
        {
            Matcher m = AbstractTableCellRenderer.whitespaceStartPattern.matcher(text.getText());
            if (m.matches())
            {
                text.getHighlighter().addHighlight(m.start(1), m.end(1), AbstractTableCellRenderer.highlightPainter);
            }
            m = AbstractTableCellRenderer.whitespaceEndPattern.matcher(text.getText());
            if (m.matches())
            {
                text.getHighlighter().addHighlight(m.start(1), m.end(1), AbstractTableCellRenderer.highlightPainter);
            }
        }
        catch (BadLocationException ble)
        {
            //
        }
    }

您可以更改JTextfield的属性,使其在其他方面看起来像jLabel。

答案 2 :(得分:2)

无法抗拒将SwingX渲染器装饰机制投入到戒指中:它解决要求的方法是实现荧光笔做它。事实上已经完成了(虽然还没有得到官方支持),但隐藏在SwingLabs-Demos项目中,名为X/MatchingTextHighlighter(你需要两者)并且最近已修复以应对图标,RToL-ComponentOrientation,alignment,椭圆..