Re: The invokeLater loop
On 5/10/2013 3:40 PM, Stefan Ram wrote:
Daniel Pitts <newsgroup.nospam@virtualinfinity.net> writes:
It is a good way to eat up CPU cycles if you don't want to have your CPU
go idle. Also known as a laptop warmer.
Say, I am writing an implementation of the ?Game Of Life?. I have an
endless main loop whose contents updates to the next generation.
I want to have a sequence like:
- calculate next generation
- update screen
- calculate next generation
- update screeen
- calculate next generation
- ...
I think that I can do this by calculating the next generation and
updating the screen in ?paintComponent? and then ?invokingLater?
paintComponent or requesting a screen update which indirectly will
call ?paintComponent? again. This will give the sequence above.
How long does "calculate the next generation" take?
- If it takes "significant" time, you're tying up the EDT
and making the GUI unresponsive during the calculation.
- If it takes "insignificant" time, you might as well just
go ahead and do the deed without all the fuss and bother.
Either way, I see no use case for the scheme. (Also, I don't
think you can rely on having one paintComponent() call per update:
If your GUI gets minimized everything might just freeze, or if
another window obscures part of your GUI you might get multiple
paintComponent() calls to refresh the display, or multiple calls
with different clip regions to paint around the intruder. You
need some extra work to make sure paintComponent() only calls
invokeLater() "when appropriate.")
Another possibility might be to calculate the next generation in
a separate thread (SwingWorker). But I am not sure how to get
the above sequence (without waiting an arbitrary period of
times or complicated handshaking across thread boundaries).
Leapfrogging a Runnable from EDT moment to EDT moment with
multiple invokeLater() self-invocations ... What a splendid way
to avoid complication!
It'd be simple enough to do it with a SwingWorker, if you
wanted to. The GUI would create a SwingWorker instance to compute
one generation and call execute() to start it, running its
doInBackground() method on a worker thread. When doInBackground()
finishes, the SwingWorker's done() method runs on the EDT, where
it can paint the display, and create and launch another SwingWorker
for the next generation. Easy-peasy.
Personally, I'd do it by driving things from the calculation
thread: Compute a new generation, compute the changes, send the
changes to the EDT via invokeLater() while the calculation thread
starts work on the next generation. Easy to control the frames-
per-second rate, too, which I think would be horribly difficult
using EDT-multiplexing.
Perhaps there's an application for the leapfrog technique, but
I've not yet heard or thought of one.
--
Eric Sosman
esosman@comcast-dot-net.invalid