如何突出显示 JLabel 的一部分?

发布于 2024-09-15 12:08:18 字数 417 浏览 3 评论 0原文

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

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

如果我使用 jlabel 以外的组件,那么它会使我的表格单元格看起来很奇怪。有人有什么建议吗?谢谢

Before any one suggests HTML, I explain later why thats not an option here. I have a table that contains a column with text cells in it. I need to be able to highlight some of the text in each cell. So for example if the cell contained "cat foo dog"... I might want to highlight foo.

My current method is to use a custom TableCellRenderer that puts html into a JLabel component that gets rendered and for a time it was good. Then I noticed that when the text in the cell became too long to fit in the column width it just truncated the text without the normal "..." that happens normally in this case. Thus users didnt know there was more text they were not seeing. The other problem was that if the original text itself contained HTML, which in my case it does at times, the cell would not render correctly. I know I could just escape the html but I would still have the prevous problem.

If I use a component other than a jlabel then it makes my table's cells look strange. Does any one have any suggestions? Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦里兽 2024-09-22 12:08:18

好吧,这是一个解决方案。

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

这是令人痛苦的详细答案:

基本上,您可以创建一个可以突出显示内容的 JLabel 子类。我会这样做;您可能想要采取一些不同的做法:

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

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

如果您需要多个区域,只需使用一个 ArrayList 而不是一个简单的字段。取消突出显示的方法可能也很有用。

现在,您需要重写 JLabelpaintComponent 方法。在这里,您需要执行几个离散的步骤,您可能希望以不同的方法或其他方式来组织这些步骤。为了简单起见,我将把它们全部放在paint方法中。

@Override
protected void paintComponent(Graphics g) {
  ...

首先,您需要计算出突出显示的物理尺寸,这可以使用漂亮的 FontMetrics 类来完成。为您使用的 Font 创建 FontMetrics 类。

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

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

如果你想知道,我之前实际上写过类似的东西。一时兴起,我决定从 JPanel 编写自己的文本区域类型组件,这基本上就是我处理突出显示的方式。在实际项目中重新发明轮子可能很愚蠢,但它确实会教你一些可能有用的随机东西......

Well, here is a solution.

In short, you can subclass JLabel to draw the highlight manually. Override the paintComponent method to do the actual drawing and use FontMetrics to calculate where the highlighted region should be drawn.

Here is that answer in excruciating detail:

Basically, you can make a subclass of JLabel that can highlight stuff. I would do that like this; you may want to do it somewhat differently:

Add a method that tells the label which part to highlight. This could be something like this, assuming you just need one highlighted region:

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

If you need multiple regions, just have an ArrayList instead of a simple field. A method for dehighlighting would probably be useful too.

Now, you need to override the paintComponent method of JLabel. Here you need to do several discrete steps, which you may want to organize in different methods or something. For simplicity, I'll put it all in the paint method.

@Override
protected void paintComponent(Graphics g) {
  ...

First, you need to figure out the physical dimensions of the highlight, which you can do using the nice FontMetrics class. Create the FontMetrics class for the Font you're using.

  FontMetrics metrics = new FontMetrics(getFont());

Now you can get all the information you need to create a rectangle that will be the highlight. You'll need the starting position, the height and the width. To get this, you'll need two substrings of the JLabel's text as follows:

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

Now you can draw the highlighted region before drawing the rest of the label:

  g.fillRect(startX, startY, length, height);
  super.paintComponent(g);
}

Of course, if you want the highlight to span multiple rows, that will require more work.

If you were wondering, I have actually written something like this before. On a whim, I decided to write my own text area type component from a JPanel, and this was basically the way I handled highlighting. Reinventing the wheel may be stupid in an actual project, but it does teach you random stuff that may come in useful...

云淡风轻 2024-09-22 12:08:18

忍不住要把 SwingX 渲染器装饰机制扔进圈子:它解决需求的方法是实现一个荧光笔来完成它。事实上,这已经完成了(虽然尚未得到官方支持),但隐藏在 SwingLabs-Demos 项目中,名为 X/MatchingTextHighlighter (您需要两者)并且最近修复以处理图标,RToL - 组件方向、对齐方式、省略号..

Can't resist to throw the SwingX renderer decoration mechanism into the ring: its way to solve the requirement is to implement a Highlighter doing it. Which in fact is already done (though not yet in the officially supported) but hidden in the SwingLabs-Demos project, named X/MatchingTextHighlighter (you would need both) and recently fixed to cope with icons, RToL-ComponentOrientation, alignment, ellipses ..

等风来 2024-09-22 12:08:18

这是一个很好的答案,而且可能是最好的解决方案。但有些人可能会发现更简单的替代方案是使用 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。

Thats a great answer, and probably the best solution. But an alternative that some might find simpler is to use a JTextfield instead of a JLabel for rendering then you can use JTextfields highlighting capabilities i.e

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)
        {
            //
        }
    }

You can change the properties of a JTextfield so it looks like a jLabel in other respects.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文