I could not understand your first para, so my answer goes for your second para, if I understood that correctly. ;)
Swing follows single thread model. So, you should be updating the UI from Event Dispatch Thread (EDT). This thread is responsible for delivering the events to your code too, hence the name. If you are continuously updating an UI in a loop then that is going to keep the EDT busy and blocked. The end effect will be an UI which does not respond to user events. This because the events are getting queued and EDT can pick them and deliver them to your code when it becomes free.
Games typically encounter this kind of scenario. You might have noticed that games typically have one fixed rate of refresh which they call FPS (Frames Per Second). Typically maintaining 60 FPS is good enough. That is, you need to draw your UI 50 times per second, but right now it seems that your render loop (which updates the UI) is running continuously.
You need to have separate thread continuously running which is responsible for drawing the UI. This should draw into a buffer (Image
). And then invoke repaint()
on the UI element to be updated. That UI element's paintComponent()
needs to overridden, so that it can copy the image in Image
buffer and paint that on the graphics context.
Now comes the real trick. The loop which calls repaint()
must do some arithmetic to make sure it does not go beyond drawing 60 times, i.e. looping 60 times, per second. If and when it does then it must call Thread.sleep(sleepTime)
, where sleepTime
is the number of milliseconds left in a second after looping 60 times. It might happen sometime that your loop may take more than a second to complete 60 iterations, then don't just go ahead for next iteration, but call Thread.yield()
. This will give other threads a chance to use the CPU, e.g. maybe your EDT. To make the matter more complicated, do not keep yielding always, so might want to put some logic to make sure that yield for only x consecutive times. This last scenario should be very rare, if at all. This scenario means the system is under heavy load.
Remember, repaint()
is thread safe and allowed to be called from any thread. It schedules a paint()
call on EDT. So, calling repaint()
does not guarantee a paint. So, you may want to experiment with different values of FPS to find the one which suites you.
By the way, the trick of rendering to an in-memory Image
is technically called Double buffer. This gives us the ability to render nice smooth animations.
Further reading:-
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…