0

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?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
euclio
  • 1,318
  • 3
  • 15
  • 18
  • 1
    I hope I'm wrong, but I'm not sure that we have enough information to be able to give you a definite correct answer. For instance, I really can't guess based on just broad descriptions why your GUI is hanging other than that you're probably still stepping on the EDT. Is the append appending to a JTextArea? Then you don't want to call that in a background thread. Rather that should be on the EDT. – Hovercraft Full Of Eels Jun 05 '12 at 02:09
  • But that won't stop me from making a guess! :) – Hovercraft Full Of Eels Jun 05 '12 at 02:16
  • I am writing on the EDT, at least according to the Eclipse debugger. Is there any other info that could help? – euclio Jun 05 '12 at 02:25
  • 1
    You appear to be slowly writing each individual character on the EDT, which is a problem. I think you need to use a StringBuilder to buffer your writing off of the EDT. – Hovercraft Full Of Eels Jun 05 '12 at 02:27
  • 1
    For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Jun 05 '12 at 02:41

1 Answers1

4

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);
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • This fixes the GUI completely freezing, but there is still significant delay. I think we are on the right track here. – euclio Jun 05 '12 at 04:07
  • @euclio: for better help, consider looking to creating an [SSCCE](http://sscce.org) as Andrew suggests. This means creating a *small* compilable and runnable program that demonstrates your problem, that we can run and test ourselves without need of outside dependencies (database, files, etc). It would require quite a bit of effort on your part to create this, but it would be well worth it both for your sake and for ours. Please check out the link for more details on just what this entails. – Hovercraft Full Of Eels Jun 05 '12 at 11:32