javaswinggraphicsjpanelpaintcomponent

How to paint a component on a JPanel?


I have been learning Java from a YouTube tutorial and when it came to carrying components in a frame, things got a bit complicated for me. There are several things in this lesson for me, such as super keyword, Graphics class and paint method. I setup a frame and added this JPanel to that frame. I wrote this practice as much as I understood but it doesn't paint the ImageIcon and opens a completely empty frame instead. Thanks to anyone who can help in advance.

public class DragPanel extends JPanel{

ImageIcon image=new ImageIcon("walle.png");
Point imageCorner;
Point prevPt;

DragPanel(){
    imageCorner=new Point(0,0);
}

public void paintComponent(Graphics g){
    super.paintComponent(g);
    image.paintIcon(this, g, (int)imageCorner.getX(), (int)imageCorner.getY());
}
}

Solution

  • ImageIcon("walle.png") is looking for the file relative to the location from which you executed the java command.

    You can check what the "working" directory is by adding System.getProperty("user.dir") to your code. You can also check to see if the file exists from within the current context using System.getProperty(new File("walle.png").exists())

    if that was the case it would cause a FileNotFoundException instead of printing null

    Actually, ImageIcon doesn't throw an exception, it simply fails silently, which is why I tend to recommend not using it.

    Instead, you should be using ImageIO, part from supporting more formats (and been expandable), it will also throw an exception if the image can't be loaded and won't return until the image is fully loaded.

    See Reading/Loading an Image for more details

    Forementioned PNG is in the same directory

    Same directory as the class or the working directory? In general, I recommend getting use to using embedded resources, as it resolves many of the issues with "execution context"

    I don't use an IDE

    I'd probably recommend making use of one as it will help solve some of these issues and let you focus on learning the language.

    So, my directory structure looks something like...

    src/
        images/
            happy.png
        stackoverflow/
            Main.java
    

    In this setup, the happy.png becomes an "embedded" resource, which will get packaged with the class files when it's exported, this means, that the resource is always in the same location, no matter the context of execution

    enter image description here

    package stackoverflow;
    
    import java.awt.Dimension;
    import java.awt.EventQueue;
    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;
    
    public class Main {
        public static void main(String[] args) {
            new Main();
        }
    
        public Main() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        JFrame frame = new JFrame();
                        frame.add(new TestPane());
                        frame.pack();
                        frame.setLocationRelativeTo(null);
                        frame.setVisible(true);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private BufferedImage image;
    
            public TestPane() throws IOException {
                image = ImageIO.read(getClass().getResource("/images/happy.png"));            
            }
    
            @Override
            public Dimension getPreferredSize() {
                return image == null ? new Dimension(200, 200) : new Dimension(image.getWidth(), image.getHeight());
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                if (image == null) {
                    return;
                }
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - image.getWidth()) / 2;
                int y = (getHeight() - image.getHeight()) / 2;
                g2d.drawImage(image, x, y, this);
                g2d.dispose();
            }
    
        }
    }