Search code examples
javaswingscrollpane

JScrollPane blank until you scroll.


I have a JScrollPane implemented like so in the frame:

public ImagePanel imgPane = new ImagePanel();    
JScrollPane scrollPane = new JScrollPane(imgPane);

ImagePanel is an extension of JPanel:

public class ImagePanel extends JPanel {

private BufferedImage img;

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

}

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

protected Point getImageLocation() {

    Point p = null;
    if (img != null) {
        int x = (getWidth() - img.getWidth()) / 2;
        int y = (getHeight() - img.getHeight()) / 2;
        p = new Point(x, y);
    }
    return p;

}
public void setImage(BufferedImage bi) {
    img = bi; 
}
public Point toImageContext(Point p) {
    Point imgLocation = getImageLocation();
    Point relative = new Point(p);
    relative.x -= imgLocation.x;
    relative.y -= imgLocation.y;
    return relative;
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    if (img != null) {
        Point p = getImageLocation();
        g.drawImage(img, p.x, p.y, this);
    }
}

The trouble I'm having is, when I load an image into the Pane:

frame.imgPane.setImage(img);

unless the previous image was the same size, the pane appears blank, no image, until you scroll. imgPane.repaint() has no effect on this. Is there a way to cause the JScrollPane to adjust to the new image without the user having to scroll?

Thanks


Solution

  • The setImage(...) method should also invoke:

    img = bi; 
    revalidate(); // to invoke the layout manager
    repaint();  // paint itself