Reputation: 2055
I have a SwingWorker that reads and processes a file in the background, after which it formats and displays the data with various styles in a JTextPane.
If the file is large (over 200K), I'll display a dialog with a progress bar. In the done() method of the SwingWorker I populate the JTextPane and then hide the dialog. The done() method looks like this:
protected void done() {
populateTextPane();
hideProgressDialog();
System.out.println("After hideProgressDialog");
}
When it runs, I'll see the dialog disappear and the println message at the console, but then the GUI freezes for another 10-15 seconds, with the data becoming visible in the JTextPane at the end of that freeze.
I thought that whatever happened in the done() method would take place in the Event Dispatch Thread. But apparently the JVM is spawning another thread to hide the dialog and execute the println while populating the JTextPane. I want to keep the progress dialog displayed until the GUI is ready to accept user input again ... how do I detect when everything in the done() is REALLY done?
Upvotes: 1
Views: 559
Reputation: 51524
Sounds like the populateTextPane is a long-running process on the EDT - which you don't want. Try to split it up: SwingWorker has api supports publishing intermediate results.
Something like
@Override
public Void doInBackground() throws Exception {
...
while (!reader.isReady()) {
publish(reader.readLine());
}
return null;
}
@Override
protected void process(List<String> lines) {
for(String line: lines) {
textPane.append(line);
}
}
Upvotes: 1
Reputation: 36601
The done
method is executed on the EDT. If you doubt this, you could always check this with the EventQueue.isDispatchThread()
method.
A possible explanation is that the populateTextPane()
method schedules a repaint of the JTextPane
on the EDT. This would mean the done()
method is finished before you see the results of the populateTextPane()
method in your UI.
You could try to rewrite the done
method as follows
protected void done() {
populateTextPane();
SwingUtilities.invokeLater( new Runnable(){
@Override
public void run(){
hideProgressDialog();
System.out.println("After hideProgressDialog");
}
} );
}
This will make sure the hideProgressDialog
is only executed after any possible Runnable
the populateTextPane()
schedules on the EDT. However, this will still freeze your UI for 10-15 seconds. Only difference is that the progress dialog is still visible.
Not sure whether this will work if the progress dialog is shown on top of the JTextPane
. The RepaintManager
might decide to only repaint the JTextPane
after the dialog became invisible (hence no longer hiding the JTextPane
).
Upvotes: 6