Question of the Week No. 45
Researched by Dave Adair
Question of the Week presents answers to key questions posed by
the developer community. The intent is to pass this important, but
not always easy-to-find, information on to Java Developer
ConnectionSM (JDC) members. The
questions are selected from the JDC newsgroups generally because:
they are frequently asked, they are significant or timely, or their
answers are not easily accessible.
Note: If you have a question to which you need an answer, try the
JDC newsgroups. You can
read through the existing newsgroups, or with your free
JDC membership, you can post new messages or threads.
Topic:
Multithreading
Question:
How can I show a JFrame that tells the user
to wait while loading a file?
I posted this problem a while ago... now I did my reading about
threads so I can describe it more clearly:
My software should load obj files. Loading is time-expensive.
While loading, I want to show a JFrame that tells the user to wait,
possibly with a JProgressBar inside it. The problem is, the wait
frame won't paint itself until AFTER the main program finishes
loading. This is the code I use, the current thread here is the
Event Dispatching Thread:
WaitFrame frame = new WaitFrame(
"Loading file please wait..."); //WaitFrame extends JFrame
frame.show();
load(fileName); //this method is time consuming
frame.dispose();
If I understand correctly, the code associated with
frame.show() gets executed in a different thread, Event Queue Thread
or something similar.. If that is the case, then what I need to do
is somehow tell Event Dispatching Thread to wait until that other
thread is done showing the frame, then proceed with load(). I was
thinking about Thread.join() would that do the trick? or is there a
more standard way to do it?
Halim
Answer:
I implemented a feature like this in an application. The
important thing is to realize that while "load(fileName)" is
executing on the Event Queue Thread, nothing UI-related can occur.
Even if you update the progress bar, it can't be repainted because
paint messages get thrown onto a queue which isn't touched until
you're done with load().
The solution I found goes something like this (all done during
the event queue thread):
1) Create a ProgressMonitor object.
2) Create a SwingWorker object (see the Swing tutorial for this
class) with load() in the construct() method. The load() code is
executed in a totally new thread.
3) During your load() code, periodically update the progress
monitor with new data (pm.setProgress() and pm.setMaximum()). To be
completely safe, these calls actually should be executed back on the
event queue thread! You can do this by calling
SwingUtilities.invokeLater(). Doing this too often may result in
some performance degradation--ironic because performance was the
problem in the first place!
I hope this helps. Sorry I don't have source code to post, but
you should get the idea from this.
-Glade
What I ended up doing was similar to what Glade suggested...
From within Event Dispatching thread, I create a low priority thread
and set it to start... that new thread processes load(filename).
Whenever I need to update my GUI during loading, the new thread
notifies Event Dispatching thread to do so... because the latter has
higher priority, it takes control right away and updates the GUI
before loading continues.
Halim
Many thanks to JDC member gladed for contributing to
this answer.
THE INFORMATION PROVIDED IN THE JAVA DEVELOPER'S
CONNECTION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR, AND NON-INFRINGEMENT.
THIS INFORMATION IS PROVIDED AT NO CHARGE. BY USE OF THE
INFORMATION YOU AGREE THAT NEITHER SUN MICROSYSTEMS, INC. NOR ITS
LICENSORS WILL BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING
DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS
PROFITS OR SPECIAL DAMAGES, EVEN IF SUN OR ITS LICENSORS HAVE BEEN
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW
THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR
INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.
THIS INFORMATION COULD INCLUDE TECHNICAL INACCURACIES OR
TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE
INFORMATION HEREIN. SUN MICROSYSTEMS, INC. MAY MAKE IMPROVEMENTS AND
OTHER CHANGES IN THE PRODUCTS AND THE PROGRAMS DESCRIBED HEREIN AT
ANY TIME WITHOUT NOTICE.