Fix an unresponsive GUI due to JTextArea?

546 Views Asked by At

I am designing a program that has a JEditorPane where users can enter and compile Java code. They can then run their program in a new process, and then their output will be displayed in a JTextArea. I accomplish this by extending JTextArea and adding this as a member:

private OutputStream writer = new OutputStream() {
    public void write(int b) {
        Console.this.append(String.valueOf((char) b));
    }
};

I then have a simple getStream() method that returns this OutputStream wrapped in a PrintWriter, and call System.setOut() and System.setErr() with the PrintWriter.

Now here comes the issue: if the user compiles a program where a lot of output is sent to the Console at once (e.g., infinite loop of System.out.println() calls), the entire GUI hangs. I have attempted to fix this by using a SwingWorker to handle the append() calls but nothing seems to work.

Is there a way to keep the GUI responsive even if massive amounts of text are being written to the JTextArea? I'm assuming part of the issue is the amount of time time that is taken to update the GUI after an append() call. Is there maybe a way to delay writing to the JTextArea by a small amount so that a user can click the button to terminate the process?

1

There are 1 best solutions below

2
On

I wonder if your problem is the way you're writing in your OutputStream. Perhaps you should write to a StringBuilder object off of the EDT, and then when a "\n" comes along, append the String on the EDT to the JTextArea.

Something like this:

// this is all called in a background thread
public void write(int b) throws IOException {

  if (b == '\r')
     return;

  if (b == '\n') {
     final String text = sb.toString() + "\n";
     SwingUtilities.invokeLater(new Runnable() {
        // except this is queued onto the event thread.
        public void run() {
           textArea.append(text);
        }
     });
     sb.setLength(0);

     return;
  }

  sb.append((char) b);
}