tpm900 tpm900 - 16 days ago 5
Java Question

Width and Height must be non-zero when scaling image for JPanel

I am trying to scale an image to fit within a JPanel in my GUI. Whenever I create a new instance of

ImagePanel
in my JFrame, I get an exception because the width and the height are both 0. However, I overrode
getPreferredSize()
so it seems like the width and height should be non-zero values.

public class ImagePanel extends JPanel {

private Image image;

public ImagePanel() {
try {
image = ImageIO.read(new File("resources/opening.jpg"));
image = scaleImage(image);
} catch (IOException e) {
e.printStackTrace();
}
}

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

public void setImage(Image i) {
image = scaleImage(i);
}

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

public Image scaleImage(Image i) {
return i.getScaledInstance(getWidth(), getHeight(), Image.SCALE_SMOOTH);
}
}


Here is the stack trace:

Exception in thread "main" java.lang.IllegalArgumentException: Width (0) and height (0) must be non-zero
at java.awt.image.ReplicateScaleFilter.<init>(ReplicateScaleFilter.java:102)
at java.awt.image.AreaAveragingScaleFilter.<init>(AreaAveragingScaleFilter.java:77)
at java.awt.Image.getScaledInstance(Image.java:172)
at ImagePanel.scaleImage(ImagePanel.java:40)
at ImagePanel.<init>(ImagePanel.java:18)
at GUIFrame.<init>(GUIFrame.java:44)
at main.main(main.java:6)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

Answer

A component doesn't have a size until the panel is displayed in a visible GUI.

So the solution is to do the scaling of your image dynamically in the paintComponent(...) method.

Note you can do this with the drawImage(...) method directly. Read the API there is a method that allows you to specify the width/height of the image as you paint the image.