0

How can I fix it so that the images appear? I'm using NetBeans 11.2 Java Gradle I am trying to make images of a car go forward. The JPanel pops up but no images are shown! I've been at it for a long time trying to figure this out. No error message shows up.

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

public class Main extends JPanel implements ActionListener {
    private final Timer animate;
    private final ImageIcon ImageArray[];
    private int delay = 50, FrameCount = 200, Currentframe = 0;

    public Main() {
        ImageArray = new ImageIcon[FrameCount];
        for (int i = 1; i < ImageArray.length; i++) {
            ImageArray[i] = new ImageIcon(getClass().getResource("Cartest (" + i + ").jpg"));
        }
        animate = new Timer(delay, this);
        animate.start();
    }

    public void paintConponent(Graphics g) {
        super.paintComponent(g);
        if (Currentframe >= ImageArray.length) {
            Currentframe = 0;
        }
        Currentframe++;
        ImageArray[Currentframe].paintIcon(this, g, 0, 0);
    }

    public void actionPerformed (ActionEvent e) {
        repaint();
    }

    public static void main (String args[]) {
        JFrame f= new JFrame("hello");
        Main s = new Main();
        f.add(s);
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(400,400);
    }
}
Abra
  • 19,142
  • 7
  • 29
  • 41
AbeZINX
  • 3
  • 1
  • Have you registered the ActionListener? I don't see it anywhere –  Jan 08 '21 at 09:27
  • Have you tried with `classpath:` prefix or full path to the image like it's recommended here? https://stackoverflow.com/questions/2422160/java-imageicon-wont-show-image – Tarmo Jan 08 '21 at 09:28
  • @tibetiroka How to i register ActionListener?? – AbeZINX Jan 08 '21 at 09:38
  • @tibetiroka I looked over the question and solution for said form and if your implying if the file was within my netbeans application it is. I dont know what classpath: is – AbeZINX Jan 08 '21 at 09:41
  • @AbeZINX I assume you want to show the next image after x seconds. You can use a timer for that. Try using a javax timer with 'this' as the action listener. –  Jan 08 '21 at 09:46
  • @tibetiroka did you miss this line in the code: `animate = new Timer(delay, this);` I believe this is what you refer to as _registered the ActionListener_ – Abra Jan 08 '21 at 09:51
  • My bad. Thank you. –  Jan 08 '21 at 09:52
  • 2
    Is the code in your question your actual code? You wrote the name of the method wrong. You wrote `paintCo` ___n___ `ponent` instead of `paintCo` ___m___ `ponent`. – Abra Jan 08 '21 at 10:20
  • Well spotted @Abra! That's a good reason to always add the `@Override` notation. OP: We can't run the code without images.. One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). E.G. The code in [this answer](https://stackoverflow.com/a/10862262/418556) hot links to an image embedded in [this question](https://stackoverflow.com/q/10861852/418556). – Andrew Thompson Jan 08 '21 at 11:09
  • @Abra Thank you so much I'm an idiot this worked – AbeZINX Jan 08 '21 at 15:45

2 Answers2

1

As others pointed out, you made a typo in the paintComponent method's name. The second problem is you'll get a NullpointerException due to line currentFrame = 0; (after the first iteration) as you started filling the imageArray from index 1. There's nothing wrong with the getResource part of your code, as it would've have thrown an exception on that line if no image was to be found.

Advice: Use the Override annotation when overriding a superclass' method. The compiler will start complaining about the annotation's incorrect use in case you made a typo.

This answer isn't necessarily indicative of how to do things. But it does make your code work:

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

public class Main extends JPanel implements ActionListener {

    private final Timer animate;
    private final ImageIcon imageArray[];
    private int delay = 50, frameCount = 200, currentFrame = 0;

    public Main() {

        imageArray = new ImageIcon[frameCount];


        for (int i = 1; i < imageArray.length; i++) {

            imageArray[i] = new ImageIcon(getClass().getResource("Cartest (" + i + ").jpg"));

        }

        animate = new Timer(delay, this);
        animate.start();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        repaint();
    }

    @Override
    public void paintComponent(Graphics g) {
        currentFrame++;
        if (currentFrame == imageArray.length) {
            currentFrame = 1;
        }

        imageArray[currentFrame].paintIcon(this, g, 0, 0);
    }

    public static void main (String args[]) {
        JFrame f= new JFrame("hello");
        Main s = new Main();
        f.add(s);
        f.setVisible(true);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(400,400);
    }

}
TimonNetherlands
  • 1,033
  • 1
  • 6
  • 6
  • 2
    (1-) Don't use getGraphics() to do painting. The proper way is to override the `paintComponent(...)` method as the OP does in the original code. In your Timer code you then invoke repaint() on the panel the Swing will invoke the paintComponent(...) method. – camickr Jan 08 '21 at 15:02
  • 1
    @camickr. Changed it so it's no longer a display of bad practice. – TimonNetherlands Jan 08 '21 at 15:29
  • 1
    @TimonNetherlands Thanks it was the spelling mistake have a great day – AbeZINX Jan 08 '21 at 15:47
1

This is one way of animating a car image. The OP didn't provide car images, so I created one.

Car Image

Here's the GUI I created. The car moves from right to left.

Car Animation GUI

I use the model / view / controller pattern when I create a Swing application. This model enforces a separation of concerns and allows me to focus on one part of the Swing application at a time.

So, the first thing I did was to create a Car class. The Car class holds the position of the image and the image itself.

Generally, in a Swing application, you read all the resources first, then you create your GUI. If reading the resources takes a long time, you can read the resources in a separate Thread that will run while you build the GUI.

Since I had one resource, I read it.

After I created the Car class, I created a view with one JFrame and one drawing JPanel. Generally, you create one drawing JPanel and draw everything on that one drawing JPanel.

The controller in this application is the Swing Timer. The Timer moves the car from right to left and starts over when the car reaches the left edge of the drawing JPanel.

Here's the complete runnable code.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class CarAnimationGUI implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new CarAnimationGUI());
    }
    
    private int drawingAreaWidth;
    private int drawingAreaHeight;
    private int startX, startY;
    
    private Car car;
    
    private DrawingPanel drawingPanel;
    
    public CarAnimationGUI() {
        this.drawingAreaWidth = 600;
        this.drawingAreaHeight = 200;
        this.car = new Car();
        
        BufferedImage image = car.getImage();
        this.startX = drawingAreaWidth - image.getWidth();
        this.startY = drawingAreaHeight - image.getHeight();
        car.setLocation(new Point(startX, startY));
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Car Animation GUI");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        this.drawingPanel = new DrawingPanel(drawingAreaWidth, 
                drawingAreaHeight);
        frame.add(drawingPanel, BorderLayout.CENTER);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        
        Timer animate = new Timer(50, new CarMover(startX, startY));
        animate.start();
    }
    
    public void repaint() {
        drawingPanel.repaint();
    }
    
    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;
        
        public DrawingPanel(int width, int height) {
            this.setBackground(new Color(154, 232, 208));
            this.setPreferredSize(new Dimension(width, height));
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            
            BufferedImage image = car.getImage();
            Point point = car.getLocation();
            
            g.drawImage(image, point.x, point.y, this);
        }
        
    }
    
    private class CarMover implements ActionListener {

        private final int startX, startY;
        private int x;
        
        public CarMover(int startX, int startY) {
            this.startX = startX;
            this.startY = startY;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            x -= 3;
            x = (x < 0) ? startX : x;
            car.setLocation(new Point(x, startY));
            repaint();
        }
        
    }
    
    public class Car {
        
        private final BufferedImage image;
        
        private Point location;

        public Car() {
            this.image = setImage();
        }
        
        private BufferedImage setImage() {
            try {
                return ImageIO.read(getClass()
                        .getResourceAsStream("/car.jpg"));
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }

        public BufferedImage getImage() {
            return image;
        }

        public void setLocation(Point location) {
            this.location = location;
        }

        public Point getLocation() {
            return location;
        }
        
    }

}
Gilbert Le Blanc
  • 50,182
  • 6
  • 67
  • 111