-1

I want to make an animation of an ellipse growing and shrinking in length. The animation should be continuous, so I want the length of the ellipse to grow to a certain point and then shrink back to its original for as long as the program is running. I already have the animation part of the program done, and I've come up with a solution to my problem that doesn't entirely work. What's happens is that ellipse expands to roughly the edge of the screen and then snaps back to length of 200 pixels, which also happens to be the width of the ellipse. I didn't some debugging and found that the value I used to adjust the length was incrementing smoothly, but for whatever reason the animation didn't reflect that.

Here's my code

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Canvas;
import javax.swing.JFrame;
import java.awt.geom.Ellipse2D;
public class Drawing extends Canvas
{
    public static final int FPS = 30;
    int angle=0;
    int eccent=0;
    int x=1;
    public static void main(String[] args)
    {
        JFrame frame = new JFrame("My Drawing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Drawing canvas = new Drawing();
        canvas.setSize(400,400);
        frame.add(canvas);
        frame.setVisible(true);
        //Animation loop
        while(true)
        {
            canvas.repaint();
            try { Thread.sleep(1000/FPS);} catch(Exception e){}
        }
    }
    public void paint(Graphics g){
        Image i=createImage(this.getWidth(), this.getHeight());
        Graphics2D g2D=(Graphics2D)i.getGraphics();
        g2D.rotate(Math.toRadians(angle), this.getWidth()/2, this.getHeight()/2);
        g2D.setColor(Color.BLUE);
        if((eccent<50)&&(x==1))
        {
            eccent++;
            System.out.println(eccent);
            g2D.draw(new Ellipse2D.Float(100,150,200,(250+eccent)));
            if(eccent==50)
            {
                x=0;
            }
        }
        else if((eccent>0)&&(x==0))
        {
            eccent--;
            System.out.println(eccent);
            g2D.draw(new Ellipse2D.Float(100,150,200,(250-eccent)));
            if(eccent==0)
            {
                x=1;
            }
        }
        g.drawImage(i,0,0,null);
    }
}
  • 2
    Don't use AWT components such as Canvas but rather subclass JPanel and draw within a paintComponent override to get double buffering. Nix while loops and thread sleep and use a Swing Timer instead – DontKnowMuchBut Getting Better Aug 03 '22 at 22:37
  • 1
    Also use Google to search the site for decent examples and recommendations for Swing animation – DontKnowMuchBut Getting Better Aug 03 '22 at 22:37
  • 1
    Also don't forget to call the super's method in your override – DontKnowMuchBut Getting Better Aug 03 '22 at 22:38
  • 1
    To solve the issue change `250-eccent` in your `else if` block to `250+eccent` or vice versa depending on the behaviour you want, this difference is the reason for your sudden jump in size. Let's say for example that eccent is 50, it would create an ellipse with `250+50` (300), then x gets set to 0 and the next paint update will enter the `else if` block, and the ellipse will be 250-49 (201), notice the jump from 300 to 201 (99 difference) from one loop to the other. – sorifiend Aug 03 '22 at 22:45
  • 1
    See also this [example](https://stackoverflow.com/a/37063037/230513). – trashgod Aug 03 '22 at 22:53

1 Answers1

1

To solve the issue you can change 250-eccent in your else if block to 250+eccent or vice versa depending on the behaviour you want.

The difference mentioned above is the reason for your sudden jump in size. Let's say for example that your ellipse is correctly growing in size to the point where eccent is 49 so the code entered the first if block and eccent will be incremented by 1 to become 50, this will create an ellipse with size 250+50 (300 total) then x gets set to 0 because of if(eccent==50){x=0;}.

So the next time the ellipse is painted x will be 0 so the code will enter the else if block, and eccent will be decreased by 1 to become 49, and the ellipse size will be 250-49 (201 total).

Notice the jump from 300 to 201 (99 difference) from one loop to the other. This is your issue using a - instead of a + in the else if block. To solve it simply use 250+eccent inside both the if and else if code blocks.


Also, as noted by others in comments, you should never use Thread.sleep(...) in the paint method which runs on the GUI/EDT thread, because that will make the application unresponsive to user input and it will not be able to be closed with the normal methods, and the operating system may view it as a frozen/unresponsive application which can cause a prompt in some circumstances. The better solution is to use a timer or another thread to manage the animation.

sorifiend
  • 5,927
  • 1
  • 28
  • 45