简体   繁体   中英

Java Paint Method Being Called By Graphics2D

I was working on creating a fade-in animation and I ran into a problem where whenever I try to draw a BufferedImage with:

g2d.drawImage(unknown.getScaledInstance(100, 200, BufferedImage.SCALE_SMOOTH),
10,button.getLocation().y - 200, this);

after using

.setCompositeAlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity)

My JPanel's paint method was constantly being repeatedly and continuously being called. I tried commenting out the drawImage bit and everything worked fine again. I also noticed that when I called the paint method from another class using:

answerPanel.paint(answerPanel.getGraphics());

The paint method stopped being continuously called. So could anyone shed some light on why the drawImage line is causing the paintMethod to be constantly called until I call it from another class? Thanks!

Agree with @user2864740, you should never call paint(...) directly, but I don't think that is the root of the problem here.

The last parameter to drawImage(...) (eg this ) is an ImageObserver . It receives callbacks whenever an Image is updated (changed), and will cause a repaint() (which will eventually call paint() ).

When you invoke Image.getScaledInstance(...) this will immediately return a new Image instance, but the actual scaling (or, resampling, really) will happen later. The image observer will handle "automagic" repaints of your component, as soon as (parts of) the scaled image is done. You component will be requested to repaint one or more times.

You should be able to observe the effects of this, by passing null as the last parameter, instead of this (probably, nothing will be painted, but you'll avoid the repaint loop).

The reason your component will go into a repaint loop, is because each time the component is asked to repaint itself, a new scaled instance is returned, causing a restart of the scaling and the automatic repainting by the image observer, as described above.

To fix the problem, don't use getScaledInstance() and instead, try:

g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.drawImage(unknown, 10, button.getLocation().y - 200, 100, 200, this);

Another way, would be to make sure you create the rescaled image only once, and continue using it for each repaint:

Image scaled;

public void paint(Graphics g) {
    ...

    if (scaled == null) {
        scaled = unknown.getScaledInstacnce(100, 200);
    }

    ...

    g2d.drawImage(scaled, 10, button.getLocation().y - 200, this);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM