WordSearch
— print (last updated: Feb 2, 2009) print

Select font size:
Download the WordSearch.ziparchive. For expediency you can install the project from existing sources, but it is recommended to go through the step-by-step construction.

Search and highlight in a JTextArea

When we search for a keyword in a text, it can either be considered as "standalone" word, or part of a larger word. In this example we will consider the former situation, i.e., that our keyword should not be part of a larger "word". As is common in keyword searches, we also want the search to be case-insensitive. The Java regular expression match setup is as follows:
String keyword = // the keyword, assume only alphanumeric characters
String text    = // the target text, possibly containing keywords

String patternStr = "\\b" + keyword + "\\b";

Pattern pattern = Pattern.compile(patternStr, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(text);

while (matcher.find()) {
  int start = matcher.start(), end = matcher.end();
}
The word-boundary "\b" anchors mean that if there is an adjacent character, that it is not a "word" character, thus creating a pattern that identifies a standalone keyword. The start and end positions of the matching substring (which is an occurrence of the keyword) can be used then to highlight the text in a JTextArea (or other Swing text components).

The class java.swing.text.Highlighter is used to create a highlight effect around a portion of the textarea content. Assuming that the variable ta is the JTextArea which holds the text, then we would use this code to create the desired effect:
Highlighter.HighlightPainter myPainter 
   = new DefaultHighlighter.DefaultHighlightPainter( Color.yellow );
   
ta.getHighlighter().addHighlight(start, end, myPainter);

Construction

  1. Create the new Java Application project WordSearch.
  2. Create a JFrame Form as the class views.Frame.
  3. Set the layout of Frame to be BorderLayout.
  4. Edit the Properties of the Frame, making it have Minimum Size [450,450].
  5. Drag a Menu Bar onto the Frame. Delete the Edit menu.
  6. Drag a Menu Item onto the File menu.
  7. Make the text of the menu item be "Open" and make the variable name be open.
  8. Drag a Text Area into the Frame (the center).
  9. Set the variable name of the Text Area to be display.
  10. Drag a Panel into the bottom part.
  11. Drag a Text Field and then a Button onto the Panel (anywhere).
  12. Set the layout of the Panel to be FlowLayout.
  13. Set the variable name of the Text Field to be keyfield.
  14. Edit the Properties of display, making it not editable, with linewrap checked.
  15. Edit the Properties of keyfield, making it have 15 columns
  16. Make the Button have text "Search" and make the variable name be search.
  17. Edit Frame in source mode. Add these imports:
    import java.awt.event.*;
    import javax.swing.text.Highlighter;
    
    and these member functions:
      public String getKeyFieldText() { return keyfield.getText(); }
    
      public String getDisplayText() { return display.getText(); }
    
      public void addSearchActionListener(ActionListener al) {
        search.addActionListener(al);      // Search button pressed
        keyfield.addActionListener(al);    // return typed in textfield
      }
    
      public Highlighter getDisplayHighlighter() {
        return display.getHighlighter();
      }
    
      public void setDisplayText(String text) {
        display.setText(text);
        display.setCaretPosition(0);
      }
    
      public void addOpenActionListener(ActionListener al) {
        open.addActionListener(al);
      }
    
  18. Edit Main, making the code be this:
    package wordsearch;
    
    import javax.swing.*;
    import java.awt.event.*;
    import java.io.*;
    import java.util.regex.*;
    import javax.swing.text.*;
    import java.awt.Color;
    
    import views.*;
    
    public class Main {
    
      private Frame frame = new Frame();
      private JFileChooser fc = new JFileChooser();
    
      private String readTextFile(File f) throws Exception {
        FileInputStream istr = new FileInputStream(f);
        InputStreamReader irdr = new InputStreamReader(istr); // promote
    
        int size = (int) f.length();  // get the file size (in bytes)
        char[] data = new char[size]; // allocate char array of right size
        irdr.read(data, 0, size);     // read into char array
        irdr.close();
    
        String contents = new String(data);
        return contents;
      }
    
      private void highlightWord(String keyword) {
        String patternStr = "\\b" + keyword + "\\b";
    
        Pattern pattern = Pattern.compile(patternStr, Pattern.CASE_INSENSITIVE);
    
        Matcher matcher = pattern.matcher(frame.getDisplayText());
    
        Highlighter.HighlightPainter myPainter
          = new DefaultHighlighter.DefaultHighlightPainter(Color.yellow);
    
        Highlighter displayHighlighter = frame.getDisplayHighlighter();
    
        displayHighlighter.removeAllHighlights();
    
        while (matcher.find()) {
          int start = matcher.start(), end = matcher.end();
          try {
            displayHighlighter.addHighlight(start, end, myPainter);
          } catch (Exception x) {
            x.printStackTrace(); // we did something wrong!
          }
        }
      }
    
      Main() {
        frame.setVisible(true);
    
        frame.addOpenActionListener(
          new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
              int status = fc.showOpenDialog(frame);
              if (status != JFileChooser.APPROVE_OPTION) {
                return;
              }
              try {
                frame.setDisplayText(readTextFile(fc.getSelectedFile()));
              } catch (Exception x) {
                JOptionPane.showMessageDialog(frame, x);
              }
            }
          });
    
        frame.addSearchActionListener(
          new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent evt) {
              String keyword = frame.getKeyFieldText().trim();
              if (!keyword.matches("\\w+")) {
                JOptionPane.showMessageDialog(frame, "illegal keyword");
              } else {
                highlightWord(keyword);
              }
            }
          });
      }
    
      public static void main(String[] args) { new Main(); }
    }
    
    


© Robert M. Kline