I have some code which executes a download in a separate thread, created so that the JFrame GUI will continue to update during the download. But, the purpose is completely defeated when I use Thread.join(), as it causes the GUI to stop updating. I need a way to wait for the thread to finish and still update the GUI.
Asked
Active
Viewed 2,303 times
1
-
5Check [SwingWorker](http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html) – m0skit0 Mar 30 '13 at 22:12
1 Answers
4
You can have the task that does the download also fire an event to the GUI.
For example:
Runnable task = new Runnable() {
public void run() {
// do your download
SwingUtilities.invokeLater(new Runnable() {
public void run() {
// call some method to tell the GUI that the download finished.
}
});
}
};
and then to run it, either use an Executor (preferred method) or a raw thread:
executor.execute(task);
or
new Thread(task).start();
As pointed out in the comments, you'd generally use a SwingWorker to do this kind of thing but you can also do the manual approach outlined above.
SwingWorker provides a doInBackground
method where you would stick your download logic in, a done
method where you would stick in code to notify the GUI that the download finished and a get
method to get the result of doInBackground
(if there was one).
E.g.,
class Downloader extends SwingWorker<Object, Object> {
@Override
public Object doInBackground() {
return doDownload();
}
@Override
protected void done() {
try {
frame.downloadDone(get());
} catch (Exception ignore) {
}
}
}
(new Downloader()).execute();

Matt Wonlaw
- 12,146
- 5
- 42
- 44
-
Great answer, but the first solution only updates the GUI _after_ the Thread is complete, whereas I wish to do so when the download starts. I've already attempted the second solution, but it's extremely messy, and again, doesn't seem to work until after the download completes. – Max Roncace Mar 30 '13 at 22:34
-
Can't you update the GUI right before you make the call to start the download as well then? – Matt Wonlaw Mar 30 '13 at 22:38
-
I've tried that, but for some reason, it doesn't update. Here's the code I'm using: `if (!lwjglZip.exists() || update) // both of these are true` `progress = "Downloading LWJGL";` `repaint();` `// execute thread` The progress variable is used in the paintComponent method as the string that should be drawn. – Max Roncace Mar 30 '13 at 22:46
-
I ultimately solved the problem by using JComponent.paintImmediately, which fixed repaint() waiting too long so as to let the Thread interrupt it. – Max Roncace Mar 31 '13 at 00:52
-