GUI in SwingWorker thread not updating

  • Follow


Hi, I'm facing a problem with updating a GUI of a ProgressMonitor
running in a SwingWorker thread:


I have a JFRame based GUI that performs an action which brings up a
JDialog, called A, in a SwingWorker thread. When I click the OK of
the dialog I start a long-running task.  To measure the progress I
startup a ProgressMonitor in another SwingWorker thread and return
the ProgressMonitor object from construct() so that the long running
task can call setNote() and setProgress()

This is contrary to what Sun advises - they advise that the long
running task be placed in the SwingWorker thread.

However for the above case, after the long-running task starts I
dispose() the dialog, the ProgressMonitor shows updates and everything
works fine.

The problem arises when I am in a situation similar to the above. My
program brings up a dialog, say B,  representing a state machine. Thus
when I click OK, it performs a long task and then goes back to B to
bring up the interface of the next state.  (Thus, the long-running task
must run in the dialogs thread, since I have to make sure the task is
finished so that I can go onto the next state.) As above, when I click OK,
I startup a ProgressMonitor in a seperate SwingWorker thread and start the
long-task on the thread that B is running in.

However in contrast to the first situation I *do not* call B's
dispose() method.

In this situation the ProgressMonitor comes up, but does not get
painted at all.

The only difference I can see between the two cases is that I am
not dispose()'ing the calling dialog in the second case. So I tried
doing it (as well as calling hide()) but the ProgressMonitor still
does not paint.

I have also tried to  put the calls to setNote() and setProgress()
(which are performed in the thread of the long-running task and not
the ProgressMonitor's SwingWorker thread) in a Runnable object and
called via SwingUtilities.invokeLater().  This runs fine for the
first situation, but in the second situation, the ProgressMonitor
still does not paint.

Any pointers would be greatly appreciated!

Thanks,
Rajarshi
0
Reply Rajarshi 5/8/2006 2:06:52 PM

Okay, first and foremost, (and feel free to correct me if I am wrong)
but it sounds like you are laboring under the misconception a lot of
people have about SwingWorker threads; the SwingWorker is not a Swing
thread - it is a non-Swing thread meant only to perform long running
tasks outside of the Swing event queue thread so that the UI stays
lively.

The SwingWorker thread is not meant to be used to perform Swing update
tasks - so calling a method on a Swing component that performs some UI
updating (such as painting or resizing, etc.) just won't work well or
consistently. A lot of people get away with it, but often run into
problems later.

You are on the right track with the invokeLater(), but you need to make
sure that all of your logic which actually manipulates any Swing
component that has been realized (i.e., painted to the desktop - more
or less) is called from within the Swing event thread.

One way to help accomplish this and to find threading problems with
Swing UI code is to write a utility method that looks at the thread it
is being executed in and throws an exception if it isn't the right
thread. I.E., if it is supposed to be the Swing thread and it isn't, or
if it isn't supposed to be the Swing thread and it is. This also helps
users of your components know what methods they must call from which
thread.

The method to call to determine whether you are in the Swing thread is:

SwingUtilities.isEventDispatchThread()

Keep a strong separation between logic which manipulates Swing
components (or containers of same, etc.) and logic which performs long
running tasks (such as talking to a server, or database, etc.), and use
that util method to make sure that each is running in the correct type
of thread. I have gone so far as to have event messages from the
database/server IO code sent to the Swing code, which then kicks off
Swing events (often with invokeLater()). I have found that most of the
time I don't need the SwingWorker thread unless I am passing in an
object and need to get it back out, outside of the context of events
(usually a property change event or something like that).

There are also alternatives to the SwingWorker that use more of an
event messaging paradigm - I believe these would be useful for
components like progress bars/etc.

For more than that I would have to look at the actual code and run it,
and I don't have the time for that. Hope this helps enough to solve
your problem.

0
Reply Developer 5/8/2006 9:25:25 PM


Developer Dude wrote:

> The SwingWorker thread is not meant to be used to perform Swing update
> tasks - so calling a method on a Swing component that performs some UI
> updating (such as painting or resizing, etc.) just won't work well or
> consistently. A lot of people get away with it, but often run into
> problems later.

Aah, thanks for pointing this out. It appears I had not digested the
documentation properly. Keeping this in mind I redesigned the code to
make sure that GUI updates are done in the main event dispatch thread.
And it all works nicely now!

Thanks,
Rajarshi

0
Reply Rajarshi 5/10/2006 4:49:34 PM

2 Replies
149 Views

(page loaded in 0.37 seconds)

Similiar Articles:













7/20/2012 1:29:30 PM


Reply: