1

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.

Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
Max Roncace
  • 1,277
  • 2
  • 15
  • 40

1 Answers1

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
  • _JComponent.paintImmediately_ DON'T if you aren't on the EDT! – kleopatra Mar 31 '13 at 09:27