【问题标题】:Multiple Word Highlighting in JavaJava中的多个单词突出显示
【发布时间】:2014-12-15 05:24:37
【问题描述】:

我正在尝试制作一个单词搜索引擎,它可以通过通配符搜索来查找单词,并突出显示它找到的所有单词。我已经开始搜索,但荧光笔只会突出显示它找到的第一个单词。假设我搜索 '*hat','that' 的所有实例都被突出显示,但它没有突出显示任何其他单词,例如 'what'(即使它们按找到的方式返回到控制台)。

这是我的荧光笔代码,模式匹配器返回的字符串被传递给这个方法:

public static void highlighter(String s){
    String text = displayString.getText();
    highlightStr = new DefaultHighlighter();
    painter = new DefaultHighlighter.DefaultHighlightPainter(Color.pink);
    displayString.setHighlighter(highlightStr); 
    //highlightStr.removeAllHighlights();

    for(int index = 0; index < text.length(); index++){        
        int start = text.indexOf(s, index);

        try{
            int end = start + s.length();
            highlightStr.addHighlight(start, end, painter);
            displayString.setCaretPosition(end);
        }catch(BadLocationException e){} 
    }
}

为了确保字符串都被传递给荧光笔,我已经从方法中打印了它们。

【问题讨论】:

  • 如果它们的起始索引超出当前迭代的索引,这个东西会一遍又一遍地重复突出显示相同的单词。考虑这是否会成为问题。我建议在 text.indexOf() 不返回 -1 的条件下将 for 循环更改为 while 循环。

标签: java highlight


【解决方案1】:

这个解决方案让我尝试了几次,但现在它可以工作了。它似乎做你想做的事,而且代码对我来说非常简单(至少在我现在阅读时)。

我使用正则表达式进行文本匹配(PatternMatcher 类),因为它们使代码非常简单。因此通配符模式首先需要通过compileWildcard方法转换为正则表达式。

package so27470328;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter;
import javax.swing.text.Highlighter;
import javax.swing.text.Highlighter.HighlightPainter;

public class Main {

  public static void main(String[] args) {
    final JTextArea textarea = new JTextArea(25, 80);
    textarea.setText("I'm trying to make a word search engine ... method.");
    Highlighter highlighter = new DefaultHighlighter();
    final DefaultHighlightPainter painter = new DefaultHighlightPainter(Color.pink);
    textarea.setHighlighter(highlighter);

    final JTextField highlight = new JTextField(80);
    highlight.getDocument().addDocumentListener(new DocumentListener() {

      private void updateHighlights() {
        highlight(textarea, highlight.getText(), painter);
      }

      @Override
      public void removeUpdate(DocumentEvent e) {
        updateHighlights();
      }

      @Override
      public void insertUpdate(DocumentEvent e) {
        updateHighlights();
      }

      @Override
      public void changedUpdate(DocumentEvent e) {
        updateHighlights();
      }
    });

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setLayout(new BorderLayout());
    frame.add(highlight, BorderLayout.NORTH);
    frame.add(textarea, BorderLayout.CENTER);
    frame.setPreferredSize(new Dimension(600, 400));
    frame.pack();
    frame.setVisible(true);
  }

  public static void highlight(JTextArea textarea, String textToHighlight,
      HighlightPainter painter) {
    String text = textarea.getText();
    Highlighter highlighter = textarea.getHighlighter();
    highlighter.removeAllHighlights();

    if (!textToHighlight.isEmpty()) {
      Matcher m = compileWildcard(textToHighlight).matcher(text);
      while (m.find()) {
        try {
          highlighter.addHighlight(m.start(), m.end(), painter);
        } catch (BadLocationException e) {
          throw new IllegalStateException(e); /* cannot happen */
        }
        textarea.setCaretPosition(m.end());
      }
    }
  }

  public static Pattern compileWildcard(String wildcard) {
    StringBuilder sb = new StringBuilder("\\b"); /* word boundary */
    /* the following replaceAll is just for performance */
    for (char c : wildcard.replaceAll("\\*+", "*").toCharArray()) {
      if (c == '*') {
        sb.append("\\S*"); /*- arbitrary non-space characters */
      } else {
        sb.append(Pattern.quote(String.valueOf(c)));
      }
    }
    sb.append("\\b"); /* word boundary */
    return Pattern.compile(sb.toString());
  }

}

【讨论】:

    猜你喜欢
    • 2017-08-30
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 1970-01-01
    • 2018-03-05
    相关资源
    最近更新 更多