Search code examples
javaanimationpaintcomponent

Why is a animation not updating?


import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;


public class GamePanel extends JPanel implements Runnable{
private static final long serialVersionUID = 1L;

private final int WIDTH = 400;
private final int HEIGHT = 400;

private static BufferedImage ship;
private int shipX;
private int shipY;


private boolean running;

public GamePanel(){
    super();

    setPreferredSize(new Dimension(WIDTH, HEIGHT));
    setFocusable(true);
    requestFocus();

    try {ship = ImageIO.read(new File("res/ship2.png"));} 
    catch (IOException e) {e.printStackTrace();}

    running = true;
}

private void gameUpdate() {
    shipX++;
    shipY++;
}

@Override
public void run() {
    while(running){
        gameUpdate();
        repaint();

        try {Thread.sleep(3);}
        catch (InterruptedException e){e.printStackTrace();}
    }
}


@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D) g;

    g2.setColor(Color.WHITE);
    g2.fillRect(0, 0, WIDTH, HEIGHT);


    g.drawImage(ship, shipX, shipY, 100, 100, null);
}
}


import javax.swing.JFrame;


public class Game extends JFrame{
private static final long serialVersionUID = 1L;

public Game(){
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setResizable(false);

    GamePanel g = new GamePanel();
    Thread t = new Thread(g);
    t.start();

    add(new GamePanel());

    pack();
    setVisible(true);
}

public static void main(String[] args) {
    new Game();
}

}

I have read many answers to questions like mine, but I have been stuck with this for hours. If repaint() should invoke overridden paintComponent(), why am I seeing no animation at all? I mean most things work: if I put System.out.println("test") I can see that thread is working and in debugging mode I see shipX and shipY values changing, but in the window the image is stuck at the beginning 0,0 coordinates. I've been trying everything from overriding paint(); and overriding both but nothing seems to get animation going.

Can anyone provide help?


Solution

  • The Java Docs Custom Painting Demo is very useful when learning about painting and I recommend you read it. Below is that same demo edited to move the ship in a straight line until it reaches a certain point on the panel.

    This may not be the answer you were looking for but this helped me a lot when I was learning about paint.

        package messaround;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.util.Timer;
    import java.util.TimerTask;
    import javax.imageio.ImageIO;
    import javax.swing.BorderFactory;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class Game {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGUI(); 
                }
            });
        }
    
        private static void createAndShowGUI() {
            System.out.println("Created GUI on EDT? "+
            SwingUtilities.isEventDispatchThread());
            JFrame f = new JFrame("Swing Paint Demo");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
            f.add(new MyPanel());
            f.pack();
            f.setVisible(true);
        } 
    }
    
    class MyPanel extends JPanel {
        BufferedImage boat;
        Timer timer;
    
        private int boatX = 0;
        private int boatY = 0;
        private int boatW;
        private int boatH;
    
        public MyPanel() {
            try {
                boat = ImageIO.read(new File("res/ship2.png"));
            } catch (IOException e) {
                e.printStackTrace();
            }
            boatW=boat.getWidth();
            boatH=boat.getHeight();
    
            timer = new Timer();
            timer.schedule(new TimerTask() {
                public void run() {
                    moveBoat();
                    if(boatX>100){
                        timer.cancel();
                        timer.purge();
                    }
                }} ,0, 30);
    
            setBorder(BorderFactory.createLineBorder(Color.black));
    
        }
    
        public void moveBoat(){
            repaint(boatX,boatY,boatW,boatH);
            boatX++;
            boatY++;
            repaint(boatX,boatY,boatW,boatH);
        }
    
    
        public Dimension getPreferredSize() {
            return new Dimension(250,200);
        }
    
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(boat, boatX, boatY, this);
        }  
    }