All processors that update my swing GUI from places other than by user clicks are performed using EventQueue.invokeLater (for example output generated from a long running background non-EDT thread process).
In my current scenario I have a TCPIP socket read background thread process that returns data which needs to update a JEditorPane object. I use the JEditorPane setText call. The problem is, placing the setText call in an invokeLater routine freezes the GUI for large files (example case test 19,790 KB).
My attempt to resolve this is to perform the setText action in a non-EDT background thread. This appears to solve the problem, BUT, I am concerned about best practices, because JEditorPane setText in java 7 (the JDK I’m using) is NOT thread safe.
HOWEVER trawling through the JDK code, it seems to me that the lengthy process performed here is in JDKs DefaultEditorKit.read, and within that method the only code that would effect the GUI is in the doc.insertString calls (unless I am mistaken). Now when you look at JDKs PlainDocument.java insertString method it documents that IT IS thread safe, so one would think therefore that this solution is sound.
HOWEVER...
Stress testing my application, I do some random clicks around the GUI, and currently have a tree node animation running, and during the large load below, it does appear to slow down the animation a little, hence my concern that I’ve not performed the best resolution (also very concerned about future JREs screwing me up here and therefore not relying on insertString currently being threadsafe).
I’ve investigated and seen that this question “how to handle long running JEditorPane setText” has been asked before but with no suitable answers.
QUESTION 1) Does anyone have thoughts on my current observations?
QUESTION 2) Does anyone have ideas on how I could achieve this another?
NOTE JEditorPane is my only choice here because I will be eventually supporting dynamic fonts of an IDE look and feel nature.
NOTE also that the below call is called within a EventQueue.invokeLater routine, so the initial editorPane work is in the EDT.
public void updateBigDataEditorPane( final JEditorPane editorPane, final String inStr ) {
// Update editor object and content.
editorPane.setContentType( "text/plain" );
editorPane.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N
editorPane.setDocument( editorPane.getEditorKit().createDefaultDocument() );
// Content update. NOTE in non-EDT thread to stop GUI freeze with large content.
new Thread( new Runnable() {
@Override
public void run() {
//// synchronized
synchronized( tabsLock ) {
// Set content.
editorPane.setText( inStr );
} //// synchronized
}
}).start();
}
While the answers provided were beneficial, and would be used to address specific long running EDT thread requirements, the solution I ended up using was as follows;
Use SwingWorker to perform the background non-EDT tasks (1 & 2), and then perform step 3 on completion on the EDT thread.