Yup, GKW is right, that’s definitely your problem. I think probably you’re not understanding exactly how repaint works - you’re putting the sleep at the end of paint() because you’re thinking that makes it display that picture for 300 ms, right? In actuality, repaint calls a few methods that, in the end, erase the screen and redraw everything. If you put a sleep somewhere in that process, that it’s all going to look delayed. In your case, the actual update happens when paint() finishes, and you’re doing all your draw changes and sleeps within the same paint - so it’s just going to hang with no updates until finally you’re at the last iteration, and everything will just be drawn on top of each other.
ex.)
public void paint(Graphics g)
{
g.setColor(Color.RED);
g.fillRect(0,0,10,10);
try {Thread.sleep(100);} catch (Exception e) {}
g.setColor(Color.BLUE);
g.fillRect(0,0,10,10);
try {Thread.sleep(100);} catch (Exception e) {}
g.setColor(Color.GREEN);
g.fillRect(0,0,10,10);
try {Thread.sleep(100);} catch (Exception e) {}
}
public void somewhereElse()
{
repaint();
}
When somewhereElse() is called, to all intensive purposes, it will wait 300ms (100ms + 100ms + 100ms) and then draw a green square. Why? Because the actual painting doesn’t happen as you’re imagining it - think of it as updating the canvas once every time you call repaint(), in one definitive state. So the paint() above will draw the red and the blue squares, yes, but by the end of the state the green square is what has been drawn on top.
The code below is a different story.
private Color color;
public void paint(Graphics g)
{
g.setColor(color);
g.fillRect(0,0,10,10);
}
public void somewhereBetter()
{
color = Color.RED;
repaint();
try {Thread.sleep(100);} catch (Exception e) {}
color = Color.BLUE;
repaint();
try {Thread.sleep(100);} catch (Exception e) {}
color = Color.GREEN;
repaint();
}
When somewhereBetter() is called, a red square will immediately be drawn to the screen, then 100ms later a blue square will be drawn, then 100ms later a green square will be drawn. This will look correct, but chances are we’re sleeping the main Thread so everything else will lock up in between each color being drawn - not what we want anyway.
What I recommend you do (and what GKW hinted at) is just create a variable to track time that has passed (possible only if you have some sort of loop that continually runs within which you can increment time that has passed), or come up with some other way of making time go by. My suggestion (purely because it’s the easiest given what you seem to have already) is to either use a Timer, or make another Thread and put your loop there.
Making a timer:
private Color color;
public void inMyConstructor()
{
//Start the timer with a delay of 100, because that's our pause length in this example.
//this refers to the containing class, but it must implement ActionListener. You could
//also make another class that implements ActionListener and use that instead.
javax.swing.Timer timer = new Timer(100,this);
}
public void somewhereEvenBetter()
{
timer.start();
}
public void paint(Graphics g)
{
g.setColor(color);
g.fillRect(0,0,10,10);
}
public void actionPerformed(ActionEvent e)
{
//Each 100ms when the timer gets fired, it can check to see what its
//old color was in order to decide what new color to give it.
if (color == null)
{
color = Color.RED;
}
else if (color == Color.RED)
{
color = Color.BLUE;
}
else if (color == Color.BLUE)
{
color = Color.GREEN;
}
else
{
//When it has been 100ms since green was displayed, stop the timer.
stop();
}
repaint();
}
The above will do exactly what you want, displaying red for 100ms, then blue for 100ms, then green for 100ms, before it stops. The rest of the program will be unaffected and will continue to run smoothly.
Here’s how you could do it with another Thread. Note that I don’t really recommend using Threads for something like this, typically, but your animation is structured such that this will probably be easiest for you.
public void somewhereThatWorks()
{
new Thread(new ColorThread(this)).start();
}
private class ColorThread implements Runnable
{
JPanel panel;
public ColorThread(JPanel p)
{
panel = p;
}
public void run()
{
p.color = Color.RED;
p.repaint();
try {Thread.sleep(100);} catch (Exception e) {}
p.color = Color.BLUE;
p.repaint();
try {Thread.sleep(100);} catch (Exception e) {}
p.color = Color.GREEN;
p.repaint();
}
}
Hopefully all that helps?