Search code examples
javaswingjtextarea

JTextArea setText(veryLongString) is taking too much time


I have a very long string which I get from a book. I display it in a JTextArea by using the setText() method. It freezes the UI and takes a lot of time. How do I get around that?

Here is as SSCCE:

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class SSCCE extends JFrame {

    JTextArea textArea;

    public SSCCE() {
        String text = buildLongString(400000);
        textArea = new JTextArea();
        textArea.setText(text);
        textArea.setLineWrap(true);
        add(new JScrollPane(textArea));

        setSize(400, 350);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    private String buildLongString(int length) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < length; i++) {
            builder.append("x");
        }
        return builder.toString();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new SSCCE();
            }
        });
    }

}

Solution

  • Creating a DefaultStyledDocument in a separate thread from constructing the GUI seems to be the fastest way to create a huge text area. A DefaultStyledDocument is thread safe.

    Here's the code I used to test the DefaultStyledDocument. I created text with spaces so that the Swing code to line wrap had a chance to work.

    package com.ggl.testing;
    
    import java.util.Random;
    
    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.DefaultStyledDocument;
    
    public class HugeTextArea implements Runnable {
    
        private DefaultStyledDocument   document;
    
        private JFrame                  frame;
    
        private JTextArea               textArea;
    
        public HugeTextArea() {
            this.document = new DefaultStyledDocument();
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    buildLongString(400000);
                }
            };
            new Thread(runnable).start();
        }
    
        @Override
        public void run() {
            frame = new JFrame();
            frame.setTitle("Huge Text");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            textArea = new JTextArea(document);
            textArea.setLineWrap(true);
            frame.add(new JScrollPane(textArea));
    
            frame.setSize(400, 350);
            frame.setLocationRelativeTo(null);
    
            frame.setVisible(true);
        }
    
        private void buildLongString(int length) {
            Random random = new Random();
            String[] chars = { "s", "t", "a", "y", " " };
            for (int i = 0; i < length; i++) {
                try {
                    document.insertString(document.getLength(),
                            chars[random.nextInt(chars.length)],
                            null);
                } catch (BadLocationException e) {
                    e.printStackTrace();
                }
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new HugeTextArea());
        }
    
    }