[RISOLTO] Cercare testo in una textarea ed evidenziarlo

di il
21 risposte

[RISOLTO] Cercare testo in una textarea ed evidenziarlo

Buongiorno a tutti, ho fatto una applicazione che legge un file di testo in una textarea e permette di cercare il contenuto di un textfield, con questo codice:
private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    // --------CERCA ----------------
      String inputValue = jTextField1.getText();
        int inizio = jTextArea1.getText().indexOf(inputValue);
        int lunghezza = inputValue.length();
        if (inizio == -1) {
            JOptionPane.showMessageDialog(null, "NON TROVATO");
        } else {
            jTextArea1.setSelectionStart(inizio);
            jTextArea1.setSelectionEnd(lunghezza + inizio);
            highlight(jTextArea1, inputValue);
        }
    }  
public void highlight(JTextArea textComp, String pattern) {
        removeHighlights(textComp);
        try {
            Highlighter hilite = textComp.getHighlighter();
            Document doc = textComp.getDocument();
            String text = doc.getText(0, doc.getLength());
            int pos = 0;
            // Search for pattern
            while ((pos = text.toLowerCase().indexOf(pattern.toLowerCase(), pos)) >= 0) {
                // Add highlight around pattern using private painter
                hilite.addHighlight(pos, pos+pattern.length(), textPainter);
                pos += pattern.length();
            }
        } catch (BadLocationException e) {
        }
    }
public void removeHighlights(JTextArea textComp) {
        Highlighter hilite = textComp.getHighlighter();
        Highlighter.Highlight[] hilites = hilite.getHighlights();
        for (int i=0; i<hilites.length; i++) {
        if (hilites[ i].getPainter() instanceof TextPainter) {

hilite.removeHighlight(hilites[i]);

}}} 
private Highlighter.HighlightPainter textPainter = new TextPainter(Color.yellow);

class TextPainter extends DefaultHighlighter.DefaultHighlightPainter {

    public TextPainter(Color color) {
    super(color);
    }
}
cliccando sul pulsante jButton5 mi vengono evidenziate tutte le occorrenze, ma io vorrei trovare solo la prima e ricliccando trovare la seconda ecc.
Vorrei inoltre sapere se esiste un modo più semplice di quello che ho scritto io prendendo spunto da quanto trovato in rete.

21 Risposte

  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    patel ha scritto:


    io vorrei trovare solo la prima e ricliccando trovare la seconda ecc.
    Soluzione "object oriented": trasforma il codice del tuo attuale metodo highlight in una classe in cui viene mantenuto come variabile di istanza il "pos". Quindi avrai un metodo es. nextHighlight() che passa al prossimo highlight. Chiaramente NON farai più un "while" perché non ha più senso.
    E dovrai anche rimuovere il highlight "precedente".

    patel ha scritto:


    Vorrei inoltre sapere se esiste un modo più semplice di quello che ho scritto io
    Sì può darsi si possa fare di meglio (non mi piace molto quel for con il if con test di instanceof TextPainter).
    Non ho mai usato il Highlighter, dovrei provare a scrivere io questa logica per vedere come mi viene. Se riesco in giornata lo faccio ..
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    andbin ha scritto:


    in cui viene mantenuto come variabile di istanza il "pos".
    Anzi, no! Non serve tenere il pos. Basta tenere il Highlighter.Highlight "corrente", perché vedo che espone il endOffset. Quindi per il successivo si riparte da lì (dovrei verificare ma il endOffset dovrebbe essere incluso, quindi dal endOffset+1).
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    Ti ringrazio per i consigli, ma sono troppo difficili per un principiante come me, se hai tempo potresti correggermi il codice ?
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    Ho risolto la questione di trovare solo la prima occorrenza e ricliccando trovare la seconda ecc. in questo modo :
    int inizio = 0;
     private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // --------CERCA ----------------
          String inputValue = jTextField1.getText();
            inizio = jTextArea1.getText().indexOf(inputValue, inizio);
            int lunghezza = inputValue.length();
            if (inizio == -1) {
                JOptionPane.showMessageDialog(null, "NON TROVATO");
            } else {
                jTextArea1.setSelectionStart(inizio);
                jTextArea1.setSelectionEnd(lunghezza + inizio);
                highlight(jTextArea1, inputValue);
            }
        }             
     public void highlight(JTextArea textComp, String pattern) {
            removeHighlights(textComp);
            try {
                Highlighter hilite = textComp.getHighlighter();
                    hilite.addHighlight(inizio, inizio+pattern.length(), textPainter);
                    inizio += pattern.length();
            } catch (BadLocationException e) {
            }
    rimane la domanda se si può realizzare in modo più semplice
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    Questo è un esempio completo.
    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTextArea;
    import javax.swing.SwingUtilities;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.DefaultHighlighter.DefaultHighlightPainter;
    import javax.swing.text.Highlighter;
    import javax.swing.text.JTextComponent;
    
    public class ProvaFrame1 extends JFrame {
        private static final long serialVersionUID = 1L;
    
        private JTextArea textArea;
        private ProgressiveHighlighter progrHighlighter;
        private JButton searchButton;
    
        public ProvaFrame1() {
            super("Prova");
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setSize(400, 300);
            setLocationRelativeTo(null);
    
            String msg = "Ciao, questo è un test al fine di testare il Highlighter\n";
            textArea = new JTextArea(msg + msg + msg);
    
            progrHighlighter = new ProgressiveHighlighter(textArea);
            progrHighlighter.setPainter(new DefaultHighlightPainter(Color.GREEN));
            progrHighlighter.setSearchText("test");
    
            searchButton = new JButton("CERCA");
            searchButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    progrHighlighter.nextHighlight();
                }
            });
    
            add(new JScrollPane(textArea), BorderLayout.CENTER);
            add(searchButton, BorderLayout.SOUTH);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    new ProvaFrame1().setVisible(true);
                }
            });
        }
    }
    
    
    class ProgressiveHighlighter {
        private final JTextComponent textComponent;
        private Highlighter.HighlightPainter painter;
        private String searchText;
        private Highlighter.Highlight currentHighlight;
    
        public ProgressiveHighlighter(JTextComponent textComponent) {
            this.textComponent = textComponent;
        }
    
        public void setPainter(Highlighter.HighlightPainter painter) {
            this.painter = painter;
        }
    
        public void setSearchText(String searchText) {
            this.searchText = searchText;
        }
    
        // altri getter/setter se necessari
    
        public void nextHighlight() {
            String text = textComponent.getText();
            int fromIndex = currentHighlight == null ? 0 : currentHighlight.getEndOffset() + 1;
    
            int resultIndex = text.indexOf(searchText, fromIndex);
    
            if (resultIndex < 0 && fromIndex > 0) {
                resultIndex = text.indexOf(searchText, 0);
            }
    
            if (resultIndex >= 0) {
                Highlighter highlighter = textComponent.getHighlighter();
    
                if (currentHighlight != null) {
                    highlighter.removeHighlight(currentHighlight);
                }
    
                try {
                    currentHighlight = (Highlighter.Highlight) highlighter.addHighlight(resultIndex, resultIndex+searchText.length(), painter);
                } catch (BadLocationException e) {
                    // TODO
                }
            }
        }
    }

    Nota come tutta la logica è ben incapsulata nella classe ProgressiveHighlighter. Tra l'altro ho anche gestito il fatto che la ricerca faccia il "giro" di nuovo dall'inizio! E ProgressiveHighlighter è comunque facilmente ben configurabile e riutilizzabile.
    Nota anche come l'azione sul pulsante è solo e direttamente quel nextHighlight() .

    Se c'è qualcosa di non chiaro, chiedi.
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    andbin ha scritto:


    Nota anche come l'azione sul pulsante è solo e direttamente quel nextHighlight() .

    Se c'è qualcosa di non chiaro, chiedi.
    Ottimo esempio, mi funziona bene, però quando vado a applicarlo al mio programma mi sottolinea l'istruzione
    progrHighlighter.nextHighlight();
    dicendomi che non trova il simbolo
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    patel ha scritto:


    andbin ha scritto:


    Nota anche come l'azione sul pulsante è solo e direttamente quel nextHighlight() .

    Se c'è qualcosa di non chiaro, chiedi.
    Ottimo esempio, mi funziona bene, però quando vado a applicarlo al mio programma mi sottolinea l'istruzione
    progrHighlighter.nextHighlight();
    dicendomi che non trova il simbolo
    A cosa si riferisce il messaggio? A progrHighlighter?

    Nota (l'ho visto solo ora!), ho fatto una piccola svista. Inizialmente prevedevo di tenere l'oggetto ProgressiveHighlighter come variabile "di istanza". Poi ho fatto varie cose (tra cui rinominato la classe facendola diventare ProgressiveHighlighter).
    E alla fine ho messo una variabile LOCALE progrHighlighter nel costruttore che è accessibile implicitamente dalla anonymous inner-class che ho fatto (senza che la variabile sia final, da Java 8 ).

    Tutto qui. Nel tuo caso progrHighlighter deve essere una variabile accessibile che tiene l'oggetto ProgressiveHighlighter con la stessa "durata" del JTextArea.

    EDIT: P.S. ho corretto il codice nel post precedente, mettendo progrHighlighter come prevedevo all'inizio.
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    Questo mi sembra d averlo già fatto ma non mi funziona ugualmente, allego il codice
    public class RubriFrame extends javax.swing.JFrame {
        String filename ="";
        File file = null;
        private ProgressiveHighlighter incrementalHighlighter;
       
        public void readtextfile(File file) {
            String line;
    	try {
                BufferedReader input = new BufferedReader(new FileReader(file));
                jTextArea1.setText("");
                line = input.readLine();
                while (line != null) {
    		jTextArea1.append(line + "\n");
    		line = input.readLine();
                }
                input.close();
    	} catch (IOException e) {
                JOptionPane.showMessageDialog(jTextArea1, "Can't load file "
                + e.getMessage());
    	}
        }
        public RubriFrame() {
            initComponents();
            ProgressiveHighlighter progrHighlighter = new ProgressiveHighlighter(jTextArea1);
            progrHighlighter.setPainter(new DefaultHighlighter.DefaultHighlightPainter(Color.GREEN));
            progrHighlighter.setSearchText(jTextField1.getText());
        }
       
        @SuppressWarnings("unchecked")
        // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    
        private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // --------CERCA ----------------
          progrHighlighter.nextHighlight(); ////////// sottolineato in rosso
        }                                        
        public static void main(String args[]) {
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new RubriFrame().setVisible(true);
                }
            });
        }
    }
    class ProgressiveHighlighter {
        private final JTextComponent textComponent;
        private Highlighter.HighlightPainter painter;
        private String searchText;
        private Highlighter.Highlight currentHighlight;
    
        public ProgressiveHighlighter(JTextComponent textComponent) {
            this.textComponent = textComponent;
        }
    
        public void setPainter(Highlighter.HighlightPainter painter) {
            this.painter = painter;
        }
    
        public void setSearchText(String searchText) {
            this.searchText = searchText;
        }
    
        // altri getter/setter se necessari
    
        public void nextHighlight() {
            String text = textComponent.getText();
            int fromIndex = currentHighlight == null ? 0 : currentHighlight.getEndOffset() + 1;
    
            int resultIndex = text.indexOf(searchText, fromIndex);
    
            if (resultIndex < 0 && fromIndex > 0) {
                resultIndex = text.indexOf(searchText, 0);
            }
    
            if (resultIndex >= 0) {
                Highlighter highlighter = textComponent.getHighlighter();
    
                if (currentHighlight != null) {
                    highlighter.removeHighlight(currentHighlight);
                }
    
                try {
                    currentHighlight = (Highlighter.Highlight) highlighter.addHighlight(resultIndex, resultIndex+searchText.length(), painter);
                } catch (BadLocationException e) {
                    // TODO
                }
            }
        }
    }
    
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    patel ha scritto:


    Questo mi sembra d averlo già fatto ma non mi funziona ugualmente, allego il codice
    Stai facendo confusione, grazie (a causa, scusa) della mia svista.

    Hai la variabile "di istanza"

    private ProgressiveHighlighter incrementalHighlighter;

    Ma poi nel costruttore hai definito una variabile LOCALE.

    ProgressiveHighlighter progrHighlighter = new ProgressiveHighlighter(jTextArea1);

    All'interno di jButton5ActionPerformed ovviamente NON è possibile "vedere" in alcun modo la variabile locale progrHighlighter nel costruttore!


    Soluzione: vedi il mio esempio corretto: ho SOLO la variabile "di istanza" progrHighlighter, la inizializzo nel costruttore e poi in qualunque metodo è lecito usarla.
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    Non ci riesco, ti dispiace correggere il mio codice ?
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    patel ha scritto:


    Non ci riesco, ti dispiace correggere il mio codice ?
    Metti:

    private ProgressiveHighlighter progrHighlighter;

    e poi nel costruttore RubriFrame() metti:

    progrHighlighter = new ProgressiveHighlighter(jTextArea1);

    (che non è una definizione di variabile, ma un assegnamento alla variabile di istanza)
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    Non ci riesco, ho provato così;
    package rubri;
    import java.awt.Color;
    import java.awt.Toolkit;
    import java.awt.datatransfer.Clipboard;
    import java.awt.datatransfer.StringSelection;
    import java.io.*;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    import javax.swing.JOptionPane;
    import javax.swing.JTextArea;
    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.DefaultHighlighter.DefaultHighlightPainter;
    
    public class RubriFrame extends javax.swing.JFrame {
        String filename ="";
        File file = null;
        
        public void readtextfile(File file) {
            String line;
            
    	try {
                BufferedReader input = new BufferedReader(new FileReader(file));
                jTextArea1.setText("");
                line = input.readLine();
                while (line != null) {
    		jTextArea1.append(line + "\n");
    		line = input.readLine();
                }
                input.close();
    	} catch (IOException e) {
                JOptionPane.showMessageDialog(jTextArea1, "Can't load file "
                + e.getMessage());
    	}
        }
        public RubriFrame() {
            initComponents();
            ProgressiveHighlighter progrHighlighter = new ProgressiveHighlighter(jTextArea1);
            progrHighlighter.setPainter(new DefaultHighlighter.DefaultHighlightPainter(Color.GREEN));
            progrHighlighter.setSearchText(jTextField1.getText());
        }
       
        @SuppressWarnings("unchecked")
        // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
     
        private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // --------CERCA ----------------
          ProgressiveHighlighter progrHighlighter;
        }                                        
    
        public static void main(String args[]) {
            /* Create and display the form */
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new RubriFrame().setVisible(true);
                }
            });
        }
    
    class ProgressiveHighlighter {
        private final JTextComponent textComponent;
        private Highlighter.HighlightPainter painter;
        private String searchText;
        private Highlighter.Highlight currentHighlight;
    
        public ProgressiveHighlighter(JTextComponent textComponent) {
            this.textComponent = textComponent;
        }
    
        public void setPainter(Highlighter.HighlightPainter painter) {
            this.painter = painter;
        }
    
        public void setSearchText(String searchText) {
            this.searchText = searchText;
        }
    
        // altri getter/setter se necessari
    
        public void nextHighlight() {
            String text = textComponent.getText();
            int fromIndex = currentHighlight == null ? 0 : currentHighlight.getEndOffset() + 1;
    
            int resultIndex = text.indexOf(searchText, fromIndex);
    
            if (resultIndex < 0 && fromIndex > 0) {
                resultIndex = text.indexOf(searchText, 0);
            }
    
            if (resultIndex >= 0) {
                Highlighter highlighter = textComponent.getHighlighter();
    
                if (currentHighlight != null) {
                    highlighter.removeHighlight(currentHighlight);
                }
    
                try {
                    currentHighlight = (Highlighter.Highlight) highlighter.addHighlight(resultIndex, resultIndex+searchText.length(), painter);
                } catch (BadLocationException e) {
                    // TODO
                }
            }
        }
    }
    ti posso allegare un link all'intero progetto ?
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    patel ha scritto:


    Non ci riesco, ho provato così;
    Stai continuando ad usare una variabile LOCALE nel costruttore RubriFrame(). Che ovviamente NON è accessibile da un altro metodo.
    public class RubriFrame extends javax.swing.JFrame {
        //...
        private ProgressiveHighlighter progrHighlighter;
    
        public RubriFrame() {
            //...
            progrHighlighter = new ProgressiveHighlighter(jTextArea1);
            //...
        }
    
        private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {
            // qui PUOI usare quella progrHighlighter
        }
    
        //...
    }
    Più chiaro di così ...
  • Re: [RISOLTO] Cercare testo in una textarea ed evidenziarlo

    Ah, una cosa, nel costruttore hai fatto

    progrHighlighter.setSearchText(jTextField1.getText());

    Questo NON va bene. Sei nel costruttore, non c'è ancora la GUI visibile a video, il campo jTextField1 è ovviamente vuoto.
    Quindi il setSearchText ti conviene farlo nel jButton5ActionPerformed.
Devi accedere o registrarti per scrivere nel forum
21 risposte