Search code examples
javaswinguser-interfacepaintcomponentrepaint

Java Swing basic animation issue


I've just started learning GUI's and Swing, and decided to write a program I found in a textbook to display a coloured rectangle and make it look like it's decreasing in size on the screen.

Below is the code I have written, my issue is that the rectangle displays on the screen, but is not repainted to a smaller size every 50ms. Can anyone point out where i'm going wrong with this?

Many thanks

import javax.swing.*;
import java.awt.*;

public class Animate {

int x = 1;
int y = 1;

public static void main(String[] args){

    Animate gui = new Animate();
    gui.start();

}

public void start(){

    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Rectangles rectangles = new Rectangles();

    frame.getContentPane().add(rectangles);
    frame.setSize(500,270);
    frame.setVisible(true);

    for(int i = 0; i < 100; i++,y++,x++){

        x++;
        rectangles.repaint();

        try {
            Thread.sleep(50);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

}





class Rectangles extends JPanel {

public void paintComponent(Graphics g){
    g.setColor(Color.blue);
    g.fillRect(x, y, 500-x*2, 250-y*2);
}

}
}

Solution

  • the rectangle displays on the screen, but is not repainted to a smaller size every 50ms

    When doing custom painting the basic code should be:

    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g); // to clear the background
    
        //  add custom painting code
    }
    

    If you don't clear the background then the old painting remains. So painting something smaller will not make a difference.

    For a better structure of your code the x/y variables should be defined in the Rectangles class. Then you should create a method like decreaseSize() which is also defined in your Rectangles class. This code will update the x/y values and then invoke repaint on itself. So your animation code will just invoke the decreaseSize() method.