Java
JPanel
Image Processing
Programming Tutorial
GUI Design

How to add an image to a JPanel?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Swing, the right way to put an image on a JPanel depends on whether the image is part of the panel's own drawing surface or just another component in the layout. Most of the time, subclassing the panel and drawing in paintComponent is the most flexible answer, while JLabel plus ImageIcon is the simplest answer for static display.

Custom Painting with paintComponent

The Swing-friendly way to render an image as part of the panel itself is:

java
1import java.awt.Dimension;
2import java.awt.Graphics;
3import java.awt.image.BufferedImage;
4import java.io.IOException;
5import javax.imageio.ImageIO;
6import javax.swing.JFrame;
7import javax.swing.JPanel;
8
9public class ImagePanel extends JPanel {
10    private final BufferedImage image;
11
12    public ImagePanel() throws IOException {
13        image = ImageIO.read(getClass().getResource("/images/logo.png"));
14        setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
15    }
16
17    @Override
18    protected void paintComponent(Graphics g) {
19        super.paintComponent(g);
20        g.drawImage(image, 0, 0, this);
21    }
22
23    public static void main(String[] args) throws Exception {
24        JFrame frame = new JFrame("Image Panel");
25        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
26        frame.add(new ImagePanel());
27        frame.pack();
28        frame.setLocationRelativeTo(null);
29        frame.setVisible(true);
30    }
31}

Important details:

  • call super.paintComponent(g) first
  • load the image once, not inside paintComponent
  • use resources or known file paths carefully

Loading in the paint method is a classic Swing performance mistake.

Scaling the Image to Fit the Panel

If the image should resize with the panel, draw it using the panel's current width and height:

java
1@Override
2protected void paintComponent(Graphics g) {
3    super.paintComponent(g);
4    g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
5}

This is easy, but you may want to preserve aspect ratio rather than stretching arbitrarily. A simple aspect-ratio version is:

java
1@Override
2protected void paintComponent(Graphics g) {
3    super.paintComponent(g);
4
5    int panelWidth = getWidth();
6    int panelHeight = getHeight();
7
8    double imageRatio = (double) image.getWidth() / image.getHeight();
9    double panelRatio = (double) panelWidth / panelHeight;
10
11    int drawWidth;
12    int drawHeight;
13
14    if (panelRatio > imageRatio) {
15        drawHeight = panelHeight;
16        drawWidth = (int) (drawHeight * imageRatio);
17    } else {
18        drawWidth = panelWidth;
19        drawHeight = (int) (drawWidth / imageRatio);
20    }
21
22    int x = (panelWidth - drawWidth) / 2;
23    int y = (panelHeight - drawHeight) / 2;
24
25    g.drawImage(image, x, y, drawWidth, drawHeight, this);
26}

Simpler Alternative: JLabel with ImageIcon

If you do not need custom painting, a label is simpler:

java
1import javax.swing.ImageIcon;
2import javax.swing.JFrame;
3import javax.swing.JLabel;
4import javax.swing.JPanel;
5
6public class IconPanelExample {
7    public static void main(String[] args) {
8        JFrame frame = new JFrame("ImageIcon Example");
9        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
10
11        JPanel panel = new JPanel();
12        panel.add(new JLabel(new ImageIcon(IconPanelExample.class.getResource("/images/logo.png"))));
13
14        frame.add(panel);
15        frame.pack();
16        frame.setLocationRelativeTo(null);
17        frame.setVisible(true);
18    }
19}

This is good when the image is just another child component in the layout rather than the panel's own background or canvas content.

When to Use Which Approach

Use custom painting when:

  • the image is part of the panel's visual surface
  • you need custom positioning or scaling
  • you want overlays, drawing, or animation

Use JLabel plus ImageIcon when:

  • the image is static
  • layout managers should position it like any other component
  • you do not need custom painting logic

Resource Loading Advice

Hard-coded file system paths make Swing apps brittle. Loading from the classpath is usually better:

java
BufferedImage image = ImageIO.read(getClass().getResource("/images/logo.png"));

That works more reliably when the app is packaged as a JAR, as long as the image is bundled into the resources.

If the resource may be missing, guard against a null URL before reading it so the failure is explicit and easier to diagnose.

Common Pitfalls

The most common mistake is overriding paint instead of paintComponent for normal Swing component rendering. paintComponent is the right hook for a panel's custom drawing.

Another issue is loading the image inside paintComponent. That code may run many times during repaints and quickly becomes slow and wasteful.

Finally, be careful with file paths. Code that works in the IDE with new File("...") often breaks once the application is packaged. Classpath resource loading is usually the safer choice.

Summary

  • The usual Swing solution is to subclass JPanel and draw the image in paintComponent.
  • Call super.paintComponent(g) and load the image once outside the paint method.
  • Use scaled drawing when the image should resize with the panel.
  • Use JLabel plus ImageIcon for simple static image display.
  • Prefer classpath resources over fragile hard-coded file paths.

Course illustration
Course illustration

All Rights Reserved.