Search code examples
javaswingjtextpane

How to Unhighlight the text in JTextPane


I have write a code to find a word in JTextPane. Problem here is when I enter a search word and click on search button it was highlight the all the occurrence of the given search word. I want to Highlight the first occurrence of the word then click on search button shows second occurrence of the way like that. Another one is it was not unHighlight the after search complete when click on text pane.

My code:

public class FindAWord extends javax.swing.JFrame {

    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(MarkAll.class.getName()).log(
                    java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MarkAll.class.getName()).log(
                    java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MarkAll.class.getName()).log(
                    java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MarkAll.class.getName()).log(
                    java.util.logging.Level.SEVERE, null, ex);
        }
        // </editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new MarkAll().setVisible(true);
            }
        });
    }

    Highlighter.HighlightPainter myHighLightPainter = new FindAWord.MyHighightPainter(
            Color.LIGHT_GRAY);
    // Variables declaration - do not modify
    private javax.swing.JScrollPane scrollPane;
    private javax.swing.JTextField searchText;
    private javax.swing.JTextPane textPane;
    private javax.swing.JButton search;

    public FindAWord() {
        initComponents();
    }

    public void removeHighLights(JTextComponent component) {
        Highlighter hilet = component.getHighlighter();
        Highlighter.Highlight[] highLites = hilet.getHighlights();
        for (int i = 0; i < highLites.length; i++) {
            if (highLites[i].getPainter() instanceof MarkAll.MyHighightPainter) {
                hilet.removeHighlight(highLites[i]);
            }
        }
    }

    public void highLight(JTextComponent component, String patteren) {
        try {
            removeHighLights(component);
            Highlighter hLite = component.getHighlighter();
            Document doc = component.getDocument();
            String text = component.getText(0, doc.getLength());
            int pos = 0;
            while ((pos = text.toUpperCase().indexOf(patteren.toUpperCase(),
                    pos)) >= 0) {
                hLite.addHighlight(pos, pos + patteren.length(),
                        myHighLightPainter);
                pos += patteren.length();
            }
        } catch (Exception e) {
        }
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        search = new javax.swing.JButton();
        searchText = new javax.swing.JTextField();
        scrollPane = new javax.swing.JScrollPane();
        textPane = new javax.swing.JTextPane();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        search.setText("Search");
        search.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                searchActionPerformed(evt);
            }
        });

        scrollPane.setViewportView(textPane);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
                getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(
                        layout.createSequentialGroup()
                        .addGap(36, 36, 36)
                        .addComponent(search,
                                javax.swing.GroupLayout.PREFERRED_SIZE,
                                91,
                                javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(32, 32, 32)
                                .addComponent(searchText,
                                        javax.swing.GroupLayout.PREFERRED_SIZE,
                                        120,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addContainerGap(114, Short.MAX_VALUE))
                                        .addGroup(
                                                javax.swing.GroupLayout.Alignment.TRAILING,
                                                layout.createSequentialGroup().addComponent(scrollPane)
                                                .addContainerGap()));
        layout.setVerticalGroup(layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(
                        layout.createSequentialGroup()
                        .addGap(36, 36, 36)
                        .addGroup(
                                layout.createParallelGroup(
                                        javax.swing.GroupLayout.Alignment.BASELINE)
                                        .addComponent(search)
                                        .addComponent(
                                                searchText,
                                                javax.swing.GroupLayout.PREFERRED_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.PREFERRED_SIZE))
                                                .addPreferredGap(
                                                        javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                        .addComponent(scrollPane,
                                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                235, Short.MAX_VALUE)));

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

    private void searchActionPerformed(java.awt.event.ActionEvent evt) {
        if (searchText.getText().length() == 0) {
            removeHighLights(textPane);
        } else
            highLight(textPane, searchText.getText());
    }

    class MyHighightPainter extends DefaultHighlighter.DefaultHighlightPainter {
        MyHighightPainter(Color color) {
            super(color);
        }
    }
}

Solution

  • If you need just to highlight one word you don't need all the addHighlight() and removeHighlight() calls.

    Just figure out the word's offset (and length) and use setSelectionStart()/setSelectionEnd() method of the JTextPane passing the word start and start + length

    UPDATE as requested the working code

    import javax.swing.text.*;
    import java.awt.*;
    
    public class FindAWord extends javax.swing.JFrame {
    
        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 (Exception ex) {
                ex.printStackTrace();
            }
            //</editor-fold>
    
        /* Create and display the form */
            java.awt.EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new FindAWord().setVisible(true);
                }
            });
        }
        Highlighter.HighlightPainter myHighLightPainter=new    FindAWord.MyHighightPainter(Color.LIGHT_GRAY);
        // Variables declaration - do not modify
        private javax.swing.JScrollPane scrollPane;
        private javax.swing.JTextField searchText;
        private javax.swing.JTextPane textPane;
        private javax.swing.JButton search;
        public FindAWord() {
            initComponents();
        }
        public void highLight(JTextComponent component,String patteren){
            try {
                Document doc=component.getDocument();
                String text=component.getText(0,doc.getLength());
                int pos=component.getCaretPosition();
                if (pos==doc.getLength()) {
                    pos=0;
                }
                int index=text.toUpperCase().indexOf(patteren.toUpperCase(),pos);
                if (index>=0) {
                    component.setSelectionStart(index);
                    component.setSelectionEnd(index+patteren.length());
                    component.getCaret().setSelectionVisible(true);
                }
            }
            catch(Exception e){
                e.printStackTrace();
            }
        }
        @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
        private void initComponents() {
    
            search = new javax.swing.JButton();
            searchText = new javax.swing.JTextField();
            scrollPane = new javax.swing.JScrollPane();
            textPane = new javax.swing.JTextPane();
            searchText.setText("test");
            textPane.setText("test qweqw test asdasdas test");
    
            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    
            search.setText("Search");
            search.setFocusable(false);
            search.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    searchActionPerformed(evt);
                }
            });
    
            scrollPane.setViewportView(textPane);
    
            javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
            getContentPane().setLayout(layout);
            layout.setHorizontalGroup(
                    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                    .addGap(36, 36, 36)
                                    .addComponent(search, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addGap(32, 32, 32)
                                    .addComponent(searchText, javax.swing.GroupLayout.PREFERRED_SIZE, 120, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addContainerGap(114, Short.MAX_VALUE))
                            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                                    .addComponent(scrollPane)
                                    .addContainerGap())
            );
            layout.setVerticalGroup(
                    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                    .addGap(36, 36, 36)
                                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                            .addComponent(search)
                                            .addComponent(searchText, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                                    .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                    .addComponent(scrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 235, Short.MAX_VALUE))
            );
    
            pack();
        }// </editor-fold>
    
        private void searchActionPerformed(java.awt.event.ActionEvent evt) {
            highLight(textPane, searchText.getText());
        }
    
        class MyHighightPainter extends DefaultHighlighter.DefaultHighlightPainter{
            MyHighightPainter(Color color){
                super(color);
            }
        }
    }