Originally posted by Gregg Bolinger:
Well, I mispoke a bit. You still want UI updates to happen on the EDT, right? You just want to let the EDT determine the best time for it to happen. So I think in this case, it is the right thing to do since the results of the task are updating the ui. I'm all for being proven wrong though.
Well yes, we do want the UI updates to happen on the EDT. But we don't
want the executeQuery() call to run on the EDT (unless we somehow know
for sure it's going to take almost no time, which is not impossible but I'm
going discount for the remainder of this thread).
By using SwingUtilities.invokeLater() as you suggest, it will all happen
on the EDT, so the GUI will still be frozen for the duration of the call to
executeQuery(). That it happens (slightly) later instead of immediately
probably doesn't even help much, as the repaint() that will be scheduled
to redraw the unpressed button typically won't be scheduled until after
the InvocationEvent that will execute the database query.
So what we want to do is run the database query on another thread, but
update the combo box with the results (which the original code didn't
actually do, but we'll presume that was the intent) on the EDT. There
are many ways to do this, but this is what SwingWorker was designed to
do. Unfortunately, there are a lot of different versions of SwingWorker
floating around, so it has been hard to write example code that works
for everyone. Things are slightly improved now that there is a
version
of SwingWorker included with JDK6. That's the version I'll use for these
examples, but versions for earlier JDKs do exist with varying degrees of
API compatibility.
Now in my experience, the call to executeQuery() will take a while, but
it will be reasonably fast to iterate through the ResultSet it will return. In
that case it's probably easiest to instantiate a new DefaultComboBoxModel
(and populate it) in the other thread, then afterwards replace the combo
box's model in the EDT:
It is possible, though, that iterating through the ResultSet could
take a while. (Theoretically, each call to rs.getString() could even
be pulling data over the network.) If this is the case, the the previous
code still works fine. But if we want the user to be able to see the
first few Strings without having to wait while we process the rest of
them, then we could use SwingWorker's publish()/process() mechanism
to append each String individually (or in small clumps) on the EDT:
We can invoke these via
new PopulateComboBoxModelWorker(comboBoxConsignee0).execute(); or
new IncrementalPopulateComboBoxWorker(comboBoxConsignee0).execute(); [edit: Please note that I haven't actually tried these examples. I may have made typos and/or more serious errors.]
[ April 23, 2008: Message edited by: Brian Cole ]