I have this JList that I’m using as the display for System.out. I’m creating an IRC client with this JList at the bottom of the JFrame. It seems that whenever 2 or more elements are added to the JLists ListModel simultaneously, the whole JList becomes white and non-interactive until one single element is added by itself. An example of when multiple elements would be added simultaneously is when an exception prints the stack trace.
Here is the OutputStream class I have that is set as System.out…
public class LogOutputStream extends OutputStream {
String sentence = "";
boolean writing = false;
private DefaultListModel subject;
public LogOutputStream(DefaultListModel logListModel) {
this.subject = logListModel;
}
public void write(final int b) {
try {
sentence = sentence + (char) b;
if (sentence.endsWith("\n") && !sentence.isEmpty() && !sentence.equals("\t") && !sentence.equals("\r\n") && !sentence.equals("\n")) {
if (writing == false) {
writing = true;
subject.addElement(sentence.replaceAll("\n", "").replaceAll("\r", "").trim());
}
sentence = "";
writing = false;
}
}
catch (Exception e) {
e.printStackTrace(Boot.stdErr);
}
}
}
Does anyone know what’s going on here, and how it can be fixed?
It is likely a Swing concurrency issue in that you’re adding items to the JList’s model off of the event thread. This can tie up the thread and prevent it from doing its necessary actions of drawing the GUI or allowing for user interaction effectively freezing your Swing GUI.
Try making sure that you only write to the JList on the EDT (the Swing Event Dispatch Thread). Something like this will queue the
addElement(...)call on the Swing event thread:Edit 1
This is closer to something I’ve done in the past, using a StringBuilder:
Edit 2
As per this article titled Writing Your Own Java I/O Stream Classes, if you’re extending OutputStream, don’t forget to provide custom implementations for the
flush()andclose()methods.