2015-02-22 2 views
3

В JTextPane производительность выделения текста с ~ 50000 строк очень медленная. У меня есть шанс увеличить предварительную подготовку?Очень низкая производительность при подсвечивании слов в JtextPane

Вот ВПЧЭ

import java.awt.*; 
 
import java.awt.event.*; 
 
import javax.swing.*; 
 
import javax.swing.text.*; 
 
    
 
public class TextFieldUnicode { 
 
    private JTextPane textPane; 
 
    private JTextField textField; 
 
    private Document doc; 
 
    private Highlighter hilit = new DefaultHighlighter(); 
 
    private Highlighter.HighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(Color.GREEN); 
 

 
    private TextFieldUnicode() throws BadLocationException { 
 
    \t this.textPane = new JTextPane(); 
 
    \t this.textField = new JTextField(); 
 
    \t this.doc = new DefaultStyledDocument();  \t 
 
    \t 
 
    \t generateSomeText();  \t 
 
    \t addTextFieldListener(); 
 
    \t createAndShowGUI(textField); 
 
    } //end of constructor 
 
     
 
    private void generateSomeText() throws BadLocationException { 
 
    \t for(int i=0;i<=50000;i++) { 
 
    \t \t doc.insertString(doc.getLength(), "hello world, hello stackoverflow, here is some generated text "+i+"\n", null); 
 
    \t } 
 
    \t textPane.setDocument(doc); 
 
    } 
 
    
 
    //here, the text will be highlighter after a search query is inserted 
 
    private void addTextFieldListener() { 
 
    \t 
 
    \t textField.addActionListener(new ActionListener() { \t \t \t 
 
\t \t \t @Override 
 
\t \t \t public void actionPerformed(ActionEvent arg0) { 
 
\t \t \t \t float start = System.nanoTime(); //start meausuring time 
 
\t \t \t \t 
 
\t \t  \t textPane.setHighlighter(hilit);  \t 
 

 
\t \t \t \t String query = textField.getText(); 
 
\t \t \t \t String text = textPane.getText(); 
 
\t  \t \t text = text.replaceAll("[\n]+", ""); 
 
\t \t \t \t 
 
\t \t \t \t if(text != null) { \t \t \t \t \t 
 
\t \t \t \t \t int index = text.indexOf(query); //get index of word \t \t \t \t \t \t 
 
\t \t \t \t \t int len = query.length(); \t \t //get length of word 
 

 
\t \t \t \t \t while (index >= 0) { 
 
\t \t \t \t \t \t try { 
 
\t \t \t \t \t \t \t textPane.getHighlighter().addHighlight(index, index+len, painter); 
 
\t \t \t \t \t \t } catch (BadLocationException e) { 
 
\t \t \t \t \t \t \t e.printStackTrace(); 
 
\t \t \t \t \t \t } 
 
\t \t \t \t \t \t \t index = text.indexOf(query, (index+len)); 
 
\t \t \t \t \t }   
 
\t \t \t \t } 
 
\t \t \t \t float stop = System.nanoTime(); //stop meausuring time 
 
\t \t \t \t System.out.println("time="+(stop-start)/1000000000+"s"); 
 
\t \t \t } 
 
\t \t }); 
 
    } 
 
    
 
    private void createAndShowGUI(JTextField textField) { 
 
     //Create and set up the window. 
 
     JFrame frame = new JFrame("TextFieldDemo"); 
 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
 
     frame.add(textField, BorderLayout.NORTH); 
 
     frame.add(new JScrollPane(textPane), BorderLayout.CENTER);  
 
     frame.setSize(new Dimension(600, 600)); 
 
     frame.setVisible(true); 
 
    } 
 
    
 
    public static void main(String[] args) throws BadLocationException { 
 
    \t new TextFieldUnicode(); 
 
    } 
 
}

А вот скриншот моего примера: он занимает ок. 2 секунды на i5 @ 1,9GHz/8GByte Ram, когда я выделяю буквы e. Любые предложения о том, как это сделать лучше? enter image description here

+0

Возможно, алгоритм, который вы используете, неэффективен? – Sharcoux

+3

Возможно, идея «JTextPane» с 50 000 строк - это плохая идея? – EJP

+1

Проверьте это, чтобы получить некоторые идеи http://java-sl.com/JEditorPanePerformance.html и, пожалуйста, разместите свой код для анализа. – StanislavL

ответ

1

Как указано в комментариях, вы можете попробовать только выделить видимый текст. Это намного быстрее. Вот пример использования вашего кода (возможно, его можно улучшить):

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.ComponentEvent; 
import java.awt.event.ComponentListener; 

import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTextField; 
import javax.swing.JTextPane; 
import javax.swing.JViewport; 
import javax.swing.text.BadLocationException; 
import javax.swing.text.DefaultHighlighter; 
import javax.swing.text.DefaultStyledDocument; 
import javax.swing.text.Document; 
import javax.swing.text.Highlighter; 

public class TextFieldUnicode { 

    private JScrollPane scrollPane; 

    private JTextPane textPane; 

    private JTextField textField; 

    private Document doc; 

    private Highlighter hilit = new DefaultHighlighter(); 

    private Highlighter.HighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(
     Color.GREEN); 

    private TextFieldUnicode() throws BadLocationException { 
    this.textPane = new JTextPane(); 
    this.textField = new JTextField(); 
    this.doc = new DefaultStyledDocument(); 
    this.scrollPane = new JScrollPane(this.textPane); 
    this.textPane.setHighlighter(this.hilit); 

    generateSomeText(); 
    addTextFieldListener(); 
    createAndShowGUI(this.textField); 
    } // end of constructor 

    private void generateSomeText() throws BadLocationException { 
    for (int i = 0; i <= 50000; i++) { 
     doc.insertString(doc.getLength(), 
      "hello world, hello stackoverflow, here is some generated text " + i 
       + "\n", null); 
    } 
    textPane.setDocument(doc); 
    } 

    // here, the text will be highlighter after a search query is inserted 
    private void addTextFieldListener() { 
    textField.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
     paintHighlights(); 
     } 
    }); 
    textPane.addComponentListener(new ComponentListener() { 

     @Override 
     public void componentShown(ComponentEvent e) { 
     } 

     @Override 
     public void componentResized(ComponentEvent e) { 
     } 

     @Override 
     public void componentMoved(ComponentEvent e) { 
     paintHighlights(); 
     } 

     @Override 
     public void componentHidden(ComponentEvent e) { 
     } 
    }); 
    } 

    private void paintHighlights() { 
    float start = System.nanoTime(); // start measuring time 

    textPane.getHighlighter().removeAllHighlights(); 

    String query = textField.getText(); 
    String text = null; 

    JViewport viewport = scrollPane.getViewport(); 
    Rectangle viewRect = viewport.getViewRect(); 

    Point p = viewRect.getLocation(); 
    int startIndex = textPane.viewToModel(p); 

    p.x += viewRect.width; 
    p.y += viewRect.height; 
    int endIndex = textPane.viewToModel(p); 

    DefaultStyledDocument document = (DefaultStyledDocument) textPane 
     .getDocument(); 
    try { 
     text = document.getText(startIndex, endIndex - startIndex); 
    } catch (BadLocationException ex) { 
     ex.printStackTrace(); 
    } 

    if (text != null) { 
     int index = text.indexOf(query); // get index of word 
     int len = query.length(); // get length of word 

     while (index >= 0) { 
     try { 
      textPane.getHighlighter().addHighlight(startIndex + index, 
       startIndex + index + len, painter); 
     } catch (BadLocationException e) { 
      e.printStackTrace(); 
     } 

     index = text.indexOf(query, (index + len)); 
     } 
    } 
    float stop = System.nanoTime(); // stop meausuring time 
    System.out.println("time=" + (stop - start)/1000000000 + "s"); 
    } 

    private void createAndShowGUI(JTextField textField) { 
    // Create and set up the window. 
    JFrame frame = new JFrame("TextFieldDemo"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.add(textField, BorderLayout.NORTH); 
    frame.add(this.scrollPane, BorderLayout.CENTER); 
    frame.setSize(new Dimension(600, 600)); 
    frame.setVisible(true); 
    } 

    public static void main(String[] args) throws BadLocationException { 
    new TextFieldUnicode(); 
    } 
}