Java: JPanel background not scaling

Solution 1:

To dynamically scale an image you use:

//g.drawImage(img, 0, 0, null);
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);

See Background Panel for a complete implementation along with a tiling feature.

Solution 2:

I guess the "simplest" approach would be to do something like...

@Override
public void paintComponent(Graphics g) {

    super.paintComponent(g);
    Image scaled = img.getScaledInstance(getWidth(), getHeight(), Image.SCALE_SMOOTH);
    g.drawImage(scaled, 0, 0, null);

}

This is inefficient, costly and may not produce the desired results

To start with, take a look at The Perils of Image.getScaledInstance()

You could also take a look at Java: maintaining aspect ratio of JPanel background image for more details about maintaining the aspect ratio of the image and scale to fit vs scale to fill.

I would also buffer the result, so that you are not repeatedly scaling the image within the paintComponent method which might be caught often...

Updated with working example

This works fine for me...

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.HeadlessException;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestImagePane {

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

    public TestImagePane() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                try {
                    Image img = null;
                    img = ImageIO.read(new File("/path/to/image"));

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new ImagePanel(img));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException | HeadlessException exp) {
                    exp.printStackTrace();
                }
            }
        });
    }

    class ImagePanel extends JPanel {

        private static final long serialVersionUID = 1L;

        private Image img;
        private Image scaled;

        public ImagePanel(String img) {
            this(new ImageIcon(img).getImage());
        }

        public ImagePanel(Image img) {
            this.img = img;
        }

        @Override
        public void invalidate() {
            super.invalidate();
            int width = getWidth();
            int height = getHeight();

            if (width > 0 && height > 0) {
                scaled = img.getScaledInstance(getWidth(), getHeight(), Image.SCALE_SMOOTH);
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(this), img.getHeight(this));
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(scaled, 0, 0, null);
        }
    }

}