0

I have a project which prints out numbers line by line in Console and I successfully redirected this to my GUI Jframe I use for this application. However, when the numbers get printed into the TextArea, they do not show up nicely one by one like a rolling list. Instead, I see the whole TextArea flashing and printing over and over again. Once the reading is finished, everything looks correct in the TextArea. Would there be a way to set this up correctly, so that it prints nicely just like I see it doing in the Console?

Thank you very much for anything helpful!

For redirecting of the system.out, I have the following code:

package ibanchecker03;

import java.io.IOException;
import java.io.OutputStream;
import javax.swing.JTextArea;

public class CustomOutputStream extends OutputStream {    
    private JTextArea textArea;

    public CustomOutputStream(JTextArea textArea) {
        this.textArea=textArea;
    }

    @Override
    public void write(int b) throws IOException {
        // redirects data to the text area
        textArea.append(String.valueOf((char)b));
        // scrolls the text area to the end of data
        textArea.setCaretPosition(textArea.getDocument().getLength());
        // keeps the textArea up to date
        textArea.update(textArea.getGraphics());
    }
}

Then inside of the application class I have this to redirect the output:

PrintStream printStream = new PrintStream(new CustomOutputStream(display));
System.setOut(printStream);
System.setErr(printStream);

1 Answers1

1

Instead of writing each character (and updating the textArea per character), I would suggest you implement a buffer (using a StringBuilder) and append to that. Only update the textArea on flush() and do so in a separate thread. Something like,

public class CustomOutputStream extends OutputStream {
    private StringBuilder sb = new StringBuilder();
    private JTextArea textArea;

    public CustomOutputStream(JTextArea textArea) {
        this.textArea = textArea;
    }

    @Override
    public void write(int b) throws IOException {
        sb.append((char) b);
    }

    @Override
    public void flush() {
        if (sb.length() > 0) {
            final String toWrite = sb.toString();
            sb.setLength(0);
            SwingUtilities.invokeLater(() -> {
                textArea.append(toWrite);
                textArea.setCaretPosition(textArea.getDocument().getLength());
                textArea.update(textArea.getGraphics());
            });
        }
    }

    @Override
    public void close() {
        flush();
        sb = null;
    }
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • Hi, this looks like a great way of solving it. However, when I apply this, I am getting no output visible in the textArea. Something must be still missing. – Marek Ševela Mar 10 '20 at 08:45