user15532639
user15532639

Reputation:

Graphics 2D not drawing images in Java

I'm following a Java course, and the current idea is to draw an image using Java Graphics2D. I'm following the steps one by one, but it seems not to be drawing anything. The panel is shown within the frame and everything is correct, but the image is not drawn. I'm using Java 15 and the course is Java 13.

JPanel class code:

public class MyPanel extends JPanel implements ActionListener {
    Image ball;
    int x = 0;
    int y = 0;
    MyPanel(){
        this.setPreferredSize(new Dimension(PANEL_WIDTH,PANEL_HEIGHT));
        this.setBackground(Color.BLACK);
        ball = new ImageIcon("ball.png").getImage();
    }
    public void paint(Graphics g){
        Graphics2D G2D = (Graphics2D) g;
        G2D.drawImage(ball,x,y,null);}

JFrame class code:

public class MyFrame extends JFrame{
    MyPanel panel;

    MyFrame(){
        panel = new MyPanel();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.add(panel);
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }

Main class code:

new MyFrame();

I picked out most of the relevant code.

Upvotes: 2

Views: 1335

Answers (2)

Tigger
Tigger

Reputation: 439

It really looks like your image is not loaded.
As @MadProgrammer just told, new ImageIcon("ball.png") does not raise any error, and getImage() will always return something (not null), even if the file is not properly loaded.

To make sure your image is available, you can try ball.getWidth(null), and if it returns -1, then something went wrong.
You can check the root path used by the JVM ("execution" location) with System.getProperty("user.dir"), the image file has to be exactly in this folder.

I tried your code with java 1.8 and it works well.

Upvotes: 0

MadProgrammer
MadProgrammer

Reputation: 347332

First, I recommend reading through Performing Custom Painting and Painting in AWT and Swing to get a better idea of how painting in Swing should work.

I then suggest reading through Reading/Loading an Image

The "problem" with ImageIcon is that

  1. It doesn't report any errors if the load fails
  2. It loads the image in a second thread, which means you don't know (easily) when it's available

ImageIO on the hand will throw an error if the image can't be loaded, which is much easier to diagnose, and will only return AFTER the image is fully loaded and available.

One concept which can be hard to grasp when your starting is the concept of "embedded" resources. Java allows you to package "resources" along with your code. These resources live within the context of your programs class path and make it MUCH easier to load when compared to having to deal with external files.

Have a look Packaging and accessing run-time resources in a runnable Jar for some basics.

Depending on the IDE you're using, it's usually pretty easy to "copy" these resources into your project/src and allow the IDE to package itself.

The problem with a question like this is it's very, very hard for anyone to truely diagnose, as there are so many reasons why the image might not have loaded and the solution is usual one of trial and error.

Me, I'd start by just drawing some lines/rectangles and make sure that paint is been called. I'd then look at things like the image's size, to make sure it's not something like 0x0.

Runnable example

This is a simple runnable example based on comments I made above. I'm using NetBeans and the image was stored in the "Source Package" (so, along with the other source code) under the /images package

Beach Ball

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
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;

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

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage beachBall;

        public TestPane() {
            try {
                beachBall = ImageIO.read(getClass().getResource("/images/BeachBall.png"));
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (beachBall == null) {
                return;
            }
            Graphics2D g2d = (Graphics2D) g.create();
            int x = (getWidth() - beachBall.getWidth()) / 2;
            int y = (getHeight() - beachBall.getHeight()) / 2;
            g2d.drawImage(beachBall, x, y, this);
            g2d.dispose();
        }

    }
}

Upvotes: 1

Related Questions