javajtextareaswing-highlighter

Highlighter highlights all the textArea instead of a specific word and its occurrences [java]


I have some problems using the highlighter class within my textArea. My program should work like this:

In a textArea the program detects a string that should be placed in the first line (the lines of comments, marked by "#", are not taken into account), highlights it and all its occurrences throughout the textArea.

EXAMPLE:

#this is an example code
#these line are comments
 **whateverWordIsFine**  #this is the word to highlight
 //code
 //code
 **whateverWordIsFine** #occurrence to be highlighted
 //
 // 
 **whateverWordIsFine** #occurrence to be highlighted

My code, instead, just highlights all the textArea. Here's my code.

import java.awt.Color;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultHighlighter;
import javax.swing.text.Highlighter;



public class NewJFrame extends javax.swing.JFrame {

    /**
     * Creates new form NewJFrame
     */
    public NewJFrame() throws BadLocationException {
        initComponents();

        textArea.getDocument().addDocumentListener(new DocumentListener() {
            String keyWord = findKeyWord();
            @Override
            public void insertUpdate(DocumentEvent e) {
                try {
                    findOccurrences();
                } catch (BadLocationException ex) {
                    Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                try {
                    findOccurrences();
                } catch (BadLocationException ex) {
                    Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                try {
                    findOccurrences();
                } catch (BadLocationException ex) {
                    Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

            public String findKeyWord() throws BadLocationException {
                if (textArea.getText().isEmpty())
                    return "";

                String keyWord = "";

                for( String line : textArea.getText().split("\n")){
                    if( !line.startsWith("#") ){
                        int keywordEndPosition = line.indexOf("#");
                        keyWord = line.substring(0, keywordEndPosition == -1 ? line.length() : keywordEndPosition);
                        keyWord = keyWord.trim();
                        break;
                    }
                }

                return keyWord;

            }

            public void findOccurrences() throws BadLocationException {
                Highlighter highlighter = textArea.getHighlighter();
                DefaultHighlighter.DefaultHighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(Color.CYAN);

                highlighter.removeAllHighlights();

                if (keyWord.isEmpty())
                     return;
                Pattern pattern = Pattern.compile( Pattern.quote(keyWord) );
                Matcher matcher = pattern.matcher(textArea.getText());  

                while(matcher.find()) {
                    highlighter.addHighlight(matcher.start(), matcher.end(), painter);
                }

            }


        });


    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        textArea = new javax.swing.JTextArea();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        textArea.setColumns(20);
        textArea.setRows(5);
        jScrollPane1.setViewportView(textArea);

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 417, Short.MAX_VALUE)
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 292, Short.MAX_VALUE)
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>                        

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(NewJFrame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    new NewJFrame().setVisible(true);
                } catch (BadLocationException ex) {
                    Logger.getLogger(NewJFrame.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        });
    }
    // Variables declaration - do not modify                     
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea textArea;
    // End of variables declaration                   
}

Solution

  • Not sure I understand exactly how you want the program to work, but here's how I interpreted it:

    The first line that doesn't start with # contains a keyword, and this keyword should be highlighted throughout the text.

    This doesn't have to be as complicated as the code you currently have. You simply have to find the keyword, then find all the occurrences of it and highlight them.

    public String findKeyWord() throws BadLocationException {
        if( textArea.getText().isEmpty() )
            return "";
    
        String keyWord = "";
        for( String line : textArea.getText().split("\n")){
            if( !line.startsWith("#") ){
                int keywordEndPosition = line.indexOf("#"); 
                keyWord = line.substring(0, keywordEndPosition == -1 ? line.length() : keywordEndPosition );
                keyWord = keyWord.trim();
                break;
            }
        }
    
        return keyWord;
    }
    

     

    public void findOccurrences() throws BadLocationException {  
        Highlighter highlighter = textArea.getHighlighter();        
        DefaultHighlighter.DefaultHighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(Color.CYAN);
    
        highlighter.removeAllHighlights();        
    
        if( keyWord.isEmpty() )
            return;
    
        Pattern pattern = Pattern.compile( Pattern.quote(keyWord) );
        Matcher matcher = pattern.matcher(textArea.getText());                    
    
        while(matcher.find()) {
            highlighter.addHighlight(matcher.start(), matcher.end(), painter);
        }
    }
    

      And then you have to change

    findKeyWord();
    

    in all your listener functions to

    keyWord = findKeyWord();