The Event Dispatching Thread
The EDT does a number of important jobs, apart from processing system events from OS, it also handles the processing of many of the internal events, like painting.
The intention is to provide a single, unified mechanism for dealing with events within a single thread context, reducing the risk of race conditions and deadlocks and undesirable side effects like dirty/partial paints (as an object is been painted, so internal state gets changed which affects what is remaining to be painted)
First Example
public void mouseClicked(MouseEvent event) {
int targetX = event.getX();
int targetY = event.getY();
for(int i=0;i<10;++i) {
x = (x+targetX)/2;
y = (y+targetY)/2;
repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) { }
}
}
I assume that mouseClicked
is an implementation from the MouseListener
interface. MouseEvent
s pass through the EventQueue
and are processed within the EDT, meaning that mouseClicked
is called within the context of the EDT.
Until the method exists, the EDT is unable to process any further events. This means that the combination of the for-loop
and Thread.sleep
prevent the EDT from processing events for up to a second.
An important note, repaint
does not occur immediately, it posts an paint event into the EventQueue
, via the RepaintManager
.
One of the side effects the RepaintManager
is that it can consolidate repeated repaint requests down into few actual paint events.
So, as a consequence of your for-loop
/Thread.sleep
, either you are getting all your paint events in a very short time (and you simply can't see them update) or, more likely, you are getting the last one.
Second Example
class Animation extends Thread {
/* … */
public void run() {
int targetX = event.getX();
int targetY = event.getY();
for(int i=0;i<10;++i) {
panel.x = (panel.x+targetX)/2;
panel.y = (panel.y+targetY)/2;
panel.repaint();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
}
}
The second example, while on the surface looks okay, violates the single threaded rules of Swing, that is, any updates to the UI should be made from within the context of the EDT. This is to ensure that any updates don't occur between paint cycles, potentially causing dirty paints or unwanted paint artifacts.
As a general rule, repaint
is about the only method I'd consider to be thread safe (there are a couple more, but I keep things simple).
The answer...
Is, complicated, but so is animation. The basic requirements are...
- You need to know where you're starting from
- You need to know where you're going
- You need to know how you're getting there
- Updates to the components/UI should be made from within the EDT
- Waiting should be done outside the EDT
While you could achieve this using Thread
s, it becomes considerably more difficult and slightly error prone and requires some more coordination between the threads
You could use a SwingWorker
to take some of the guess work out, but most of the time, a simple Swing Timer
does a nice job
This example demonstrates, in principle, what you're trying to achieve, it's slightly more complicated, as it attempts to maintain a constent speed no matter the length of the line, but it's an example