views:

23

answers:

1

I've been spending a great deal of time trying to understand this. I created a JApplet that used Thread.sleep() in a loop to animate the applet. But when I tried to run the Applet the screen stayed blank. When I draw the animations in a separate thread and call repaint, the applet works perfectly. I've seen many explanations of why this happens but none have been very comprehensive.

What thread calls the paint method? And why can't that thread partially draw on the canvas, pause, then continue drawing? I've noticed that some Thread.sleep() calls work as expected, particularly when they are not in a loop.

A: 

UI needs to be repainted and this happens on UI thread.

Therefore you should not seize control of the UI thread - it seems that you are doing just this (animation loop with .sleep()).

You should return control of the UI thread (exit the function that you are in) so that it can be repainted.

Take a look at Swing Painting and SwingWorker to understand how to run a background thread to do some work and then update UI on UI thread.

Peter Knego
Shouldn't repaint() get invoked on the event dispatcher thread after the EDT finishes sleeping? I already fixed the problem using a worker thread, but I don't understand why that has to be done. It seems to me that the EDT should do exactly what it would normally do, just with a series of pauses.
Hurpe
Ultimately I have to be able to explain this to someone else. The purpose of this question, I guess, is to understand better why sleeping in the EDT causes the thread to malfunction. The weird thing is that the thread doesn't always die after using .sleep()
Hurpe
@1: No. Repaint does not happen until you release control of the thread - this means exiting your function. Thread.sleep() definition: `Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds` After .sleep() finishes control is given back to your code.
Peter Knego
@2: Sleeping just pauses a thread in this case the EDT. Your code running in loop actually prevents it to repaint the screen (hence black screen). Calling .repaint() just notifies RepaintManager you want a repaint which never happens if you still hold the control of EDT.
Peter Knego
EDT is used for Swing paintng (and other internal tasks) and event dispatching (mouse cliks, etc..). When an event is dispatched your method gets called on the EDT. You should do whatever you need to do quickly and exit this method so that you release control back to Swing. If you keep control (running loops, etc..) Swing will cease to work (no repaints, etc..).
Peter Knego