What is EDT ?
Swing event handling code runs on a special thread known as the event dispatch thread. Most code that invokes Swing methods also runs on this thread. This is necessary because most Swing object methods are not "thread safe". All GUI related task, any update should be made to GUI while painting process must happen on the EDT, which involves wrapping the request in an event and processing it onto the EventQueue
. Then the event are dispatched from the same queue in the one by one in order they en-queued, FIRST IN FIRST OUT. That is, if That is, if Event A
is enqueued to the EventQueue
before Event B
then event B will not be dispatched before event A.
Any task you perform which may take a while, likely to block the EDT, no dispatching will happen, no update will be made and hence your application FREEZES. You will have to kill it to get rid of this freezing state.
In your program, aside from creating your JFrame
and making it to visible from the main thread (which we also should not do):
while(true) {
if (up) {
player.moveUp();
} else if (down) {
player.moveDown();
}
repaint();
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
Logger.getLogger(Spaceshooter.class.getName()).log(Level.SEVERE, null, ex);
}
}
you are posting repaint()
request from the thread which you sent to sleep right immediately after that.
SwingUtilities.invokeLater():
Swing provides a nice function SwingUtilities.invokeLater(new Runnable(){})
for posting repaint
request to the EDT. All you have to do is to write:
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
repaint();
}
});
Now some more thing to mention:
- We should not implements a GUI component with
Runnable
. Make another class implementing Runnable
, make your computation inside that then use SwingUtilities
to post the component update request.
- we should not made custom painting on
JFrame
directly. JFrame is a top level component. It is more like a container which contains your whole app. If you want custom painting use a custom component MyCanvas extends JComponent
.
- we should not override
paint()
function. Instead paintComponent(g)
will serve our custom painting purposes nicely.
- Learn to use Swing Timer class for timely repeated GUI rendering task.
Tutorial Resource and References:
- The Event Dispatch Thread
- EventQueue
- How to Use Swing Timers
- Lesson: Performing Custom Painting
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…