Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getWidth() and getHeight() are 0 after calling setPreferredSize()

Tags:

java

swing

jpanel

I've been working on my project for a few hours now, only to be constantly frustrated at this.

I have a parent JFrame that adds a JPanel to it, and it is going to be used for the rendering and display of my simulation I'm developing. There are no swing objects that are going to be added to the JPanel, as I will only be using it for rendering shapes using a graphics object.

My code is as such below:

public class SimulationPanel extends JPanel {

private BufferedImage junction;
private Graphics2D graphics;

public SimulationPanel() {
    super();
    initPanel();

}

private void initPanel() {
    this.setPreferredSize(new Dimension(600, 600)); //TODO: bug with not sizing the junction correctly.
    junction = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
    graphics = junction.createGraphics();
    setBackground(Color.white);


    System.out.println(getWidth());
}

The code specifically breaks on the second line of the initPanel() method where I try to create a new BufferedImage.

The output from the exception states "Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: Width (0) and height (0) must be > 0"

I'm really unsure on why this is. I've tried to use past answers from Stack Overflow but they were unsuccessful in helping.

This is my first post, so I hope it isn't too bad.

Thanks.

like image 787
Daniel Bond Avatar asked Feb 22 '23 14:02

Daniel Bond


2 Answers

When you set the preferred size, you tell the various Java layout managers how you would like your panel to be laid out once it's added to a container. But until it actually is added to the container, it won't have a width or height, and even after it is, it might not have the width and height that you asked for.

One option is to just use 600 directly for the width and height of your new buffered image, and when you add the panel to the JFrame make sure you call pack() on the JFrame to allow the window to size to the preferred size of your panel.

like image 54
Mark Peters Avatar answered Mar 24 '23 10:03

Mark Peters


Create your a BufferedImage cache inside your component's paintComponent method. There, you will know the actual size of the component and take that into account for the rendering. The image acts as a cache of your component's content, but you fail to take into account that its size is part of the cached information.

@Override protected void paintComponent(Graphics g) {
  // create cache image if necessary
  if (null == image ||
      image.getWidth() != getWidth() ||
      image.getHeight() != getHeight() ||) {
    image = new BufferedImage(getWidth(), getHeight());
    imageIsInvalid = true;
  }

  // render to cache if needed
  if (imageIsInvalid()) {
    renderToImage();
  }

  // redraw component from cache
  // TODO take the clip into account
  g.drawImage(image, 0, 0, null);
}
like image 33
jackrabbit Avatar answered Mar 24 '23 08:03

jackrabbit