Java Swing How to - Highlight Word in JTextPane








Question

We would like to know how to highlight Word in JTextPane.

Answer

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Shape;
//from   ww w. j a v  a  2s  .c  om
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Document;
import javax.swing.text.Highlighter;
import javax.swing.text.JTextComponent;
import javax.swing.text.LayeredHighlighter;
import javax.swing.text.Position;
import javax.swing.text.View;

public class Main {
  public static void main(String[] args) {
    JFrame f = new JFrame();
    JPanel panel = new JPanel();
    JTextPane textPane = new JTextPane();
    JTextField tf = new JTextField("is");
    String word = "";
    Highlighter highlighter = new UnderlineHighlighter(null);

    textPane.setHighlighter(highlighter);
    textPane.setText("This is a test");
    panel.setLayout(new BorderLayout());
    panel.add(new JLabel("Enter word, then press ENTER key: "), "West");
    panel.add(tf, "Center");

    final WordSearcher searcher = new WordSearcher(textPane);
    tf.addActionListener(e -> {
      String w = tf.getText().trim();
      int offset = searcher.search(w);
      if (offset == -1) {
        return;
      }
      try {
        textPane.scrollRectToVisible(textPane.modelToView(offset));
      } catch (BadLocationException ex) {
      }

    });
    textPane.getDocument().addDocumentListener(new DocumentListener() {
      @Override
      public void insertUpdate(DocumentEvent evt) {
        searcher.search(word);
      }

      @Override
      public void removeUpdate(DocumentEvent evt) {
        searcher.search(word);
      }

      @Override
      public void changedUpdate(DocumentEvent evt) {
      }
    });
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.add(panel, "South");
    f.add(new JScrollPane(textPane), "Center");
    f.setSize(400, 400);
    f.setVisible(true);
  }
}

class WordSearcher {

  protected JTextComponent comp;
  protected Highlighter.HighlightPainter painter;

  public WordSearcher(JTextComponent comp) {
    this.comp = comp;
    this.painter = new UnderlineHighlightPainter(Color.red);
  }

  public int search(String word) {
    int firstOffset = -1;
    Highlighter highlighter = comp.getHighlighter();
    Highlighter.Highlight[] highlights = highlighter.getHighlights();
    for (int i = 0; i < highlights.length; i++) {
      Highlighter.Highlight h = highlights[i];
      if (h.getPainter() instanceof UnderlineHighlightPainter) {
        highlighter.removeHighlight(h);
      }
    }
    if (word == null || word.equals("")) {
      return -1;
    }
    String content = null;
    try {
      Document d = comp.getDocument();
      content = d.getText(0, d.getLength()).toLowerCase();
    } catch (BadLocationException e) {
      return -1;
    }
    word = word.toLowerCase();
    int lastIndex = 0;
    int wordSize = word.length();
    while ((lastIndex = content.indexOf(word, lastIndex)) != -1) {
      int endIndex = lastIndex + wordSize;
      try {
        highlighter.addHighlight(lastIndex, endIndex, painter);
      } catch (BadLocationException e) {
      }
      if (firstOffset == -1) {
        firstOffset = lastIndex;
      }
      lastIndex = endIndex;
    }
    return firstOffset;
  }
}

class UnderlineHighlighter extends DefaultHighlighter {

  protected static final Highlighter.HighlightPainter sharedPainter = new UnderlineHighlightPainter(
      null);
  protected Highlighter.HighlightPainter painter;

  public UnderlineHighlighter(Color c) {
    painter = (c == null ? sharedPainter : new UnderlineHighlightPainter(c));
  }

  public Object addHighlight(int p0, int p1) throws BadLocationException {
    return addHighlight(p0, p1, painter);
  }

  @Override
  public void setDrawsLayeredHighlights(boolean newValue) {
    super.setDrawsLayeredHighlights(true);
  }

}

class UnderlineHighlightPainter extends LayeredHighlighter.LayerPainter {
  protected Color color;

  public UnderlineHighlightPainter(Color c) {
    color = c;
  }

  @Override
  public void paint(Graphics g, int offs0, int offs1, Shape bounds,
      JTextComponent c) {
  }

  @Override
  public Shape paintLayer(Graphics g, int offs0, int offs1, Shape bounds,
      JTextComponent c, View view) {
    g.setColor(color == null ? c.getSelectionColor() : color);
    Rectangle rect = null;
    if (offs0 == view.getStartOffset() && offs1 == view.getEndOffset()) {
      if (bounds instanceof Rectangle) {
        rect = (Rectangle) bounds;
      } else {
        rect = bounds.getBounds();
      }
    } else {
      try {
        Shape shape = view.modelToView(offs0, Position.Bias.Forward, offs1,
            Position.Bias.Backward, bounds);
        rect = (shape instanceof Rectangle) ? (Rectangle) shape : shape
            .getBounds();
      } catch (BadLocationException e) {
        return null;
      }
    }
    FontMetrics fm = c.getFontMetrics(c.getFont());
    int baseline = rect.y + rect.height - fm.getDescent() + 1;
    g.drawLine(rect.x, baseline, rect.x + rect.width, baseline);
    g.drawLine(rect.x, baseline + 1, rect.x + rect.width, baseline + 1);
    return rect;
  }
}