Here is my problem. I have a method that is called from a mouse
listener. That method steps through a container of Image objects and
draws them to the JPanel - ie creates an animation. The problem is
that the mouse listener can collect events while the animation is in
progress and I want to prevent that without spawning a separate thread.
My appproach to this was to remove the listener at the top of the
animation method then at the bottom of the method, empty the event
queue and add the listener. It doesn't work. Here is pseudo code
representing this approach. Can anyone suggest a solution? Thanks in
advance
MouseListener{
public void mouseReleased(){
runAnimation();
}
}
public void runAnimation(){
removeMouseListener();
while(/*last element not reached*/){
//draw the image in current element
Thread.sleep(/*time for image to linger on screen*/);
}
//empty the event queue
EventQueue eventQueue =
Toolkit.getDefaultToolkit().getSystemEventQueue();
AWTEvent event = null;
try{
event = EventQueue.getNextEvent();
while(event != null){
event = eventQueue.getNextEvent();
}
}catch(InterruptedException iE){}
addMouseListener();
}
> Here is my problem. I have a method that is called from a mouse
> listener. That method steps through a container of Image objects and
[quoted text clipped - 6 lines]
> representing this approach. Can anyone suggest a solution? Thanks in
> advance
Can you elaborate on "It doesn't work" ? As it is, the approach seems to
be flawed - see below for why.
> MouseListener{
> public void mouseReleased(){
[quoted text clipped - 23 lines]
> addMouseListener();
> }
If you had read the API docs of the getNextEvent() method carefully,
you'd have noticed that this method will block till another event occurs
if no events are available at the time the call is made. The method to
check if any events are present is peekEvent. (which returns null if
none are present).
In any case, blocking the EDT for the duration of your animation is a
bad idea. The way I would suggest for implementing this would be using a
javax.swing.Timer as follows (pseudocode ) :
boolean animationInProgress;
int animationStep;
public void runAnimation()
{
if (!animationInProgress) // Ignores further calls if you
// already in the middle of animation
{
animationInProgress=true;
animationStep = 0;
if (performAnimationStep())
{
final javax.swing.Timer timer =
new Timer(delayPerstep, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if (!performAnimationStep())
{
timer.stop();
animationInProgress=false;
}
}
}
timer.setRepeats(true);
timer.start();
} else animationInProgress = false;
}
}
/* Performs a step in the animation process
Returns true if animation not complete,
false if completed. */
private boolean performAnimationStep()
{
// setup appropriate image to display
panel.repaint(); // call repaint() on the panel instead
// of painting on it directly. The actual painting code
// should be in the paintComponent method of the panel
animationStep++;
return animationStep < maximumStepsInAnimation;
}
BK