我无法在JPanel上查看BufferedImage图像

时间:2014-04-08 22:45:29

标签: java swing jpanel bufferedimage

我遇到以下代码的问题。如果我将图像直接加载到JPanel中,我可以看到它。但是当我在JPanel上绘制BufferedImage之前尝试先将其绘制到BufferedImage时,图像不可见。我做错了什么?

import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import java.awt.*;
import javax.swing.JPanel;

/**
 *
 * @author Duafeb
 */
public class RTester {
    BufferedImage backBuffer;
    Graphics2D g2;
    Pane pain;
    Image img;




    public RTester(){
        JFrame frame=new JFrame("Sprite Tester");
        frame.setSize(1200, 700);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        backBuffer= new BufferedImage(1200,700,BufferedImage.TYPE_INT_RGB);
        g2=backBuffer.createGraphics();
        pain=new Pane();
        frame.add(pain);
        Toolkit tk=Toolkit.getDefaultToolkit();
        img=tk.getImage(this.getClass().getResource("running.png"));


        frame.setVisible(true);
    }
      public class Pane extends JPanel{
        @Override
        public void paintComponent(Graphics g){
            Graphics2D g3=(Graphics2D)g;
            g3.drawImage(backBuffer, 0, 0, this);

        }
    }     

      public void display(){
          g2.setColor(Color.yellow);
          g2.fillRect(0, 0, pain.getWidth(), pain.getHeight());
          g2.drawImage(img, 0, 0, pain);
          pain.repaint();
      }
    public static void main(String[] args){
        RTester test=new RTester();
        test.display();
    }

}

1 个答案:

答案 0 :(得分:1)

有一些事情对此感觉不正确......

首先,您为Graphics创建BufferedImage上下文,但从不dispose。{请注意,在某些系统上,这可能会阻止内容呈现,但这可能与屏幕设备有关,而不是BufferedImage

例如,如果我改变您的代码以直接在paintComponent方法而不是BufferedImage内绘制内容,则会显示图像(在窗口变为可见之后,所有位都会瞬间显示) )。

我不确定您使用BufferedImage尝试实现的目标,但您可以直接通过paintComponent方法实现同样的目标

您可以使用Toolkit.getImage,而不是使用ImageIO.read,这可以保证在返回时,图像已完全加载(如果失败则会抛出IOException)或@ Reimeus之前建议使用MediaTracker确保在继续使用之前正确加载图像。

所以,你有四种选择......

使用MediaTracker等待加载图片...

MediaTracker mt = new MediaTracker(frame);
mt.addImage(img, 1);
try {
    mt.waitForAll();
} catch (InterruptedException ex) {
    ex.printStackTrace();
}

两个

使用ImageIO.read代替......

img = ImageIO.read(this.getClass().getResource("running.png"));

直接在paintComponent方法...

中渲染输出
@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g3 = (Graphics2D) g;
    g3.setColor(Color.yellow);
    g3.fillRect(0, 0, pain.getWidth(), pain.getHeight());
    g3.drawImage(img, 0, 0, obsever);
}

使用您自己的ImageObserver来确保在更新图像时,将其重新渲染到后备缓冲区...

private MyImageObsever obsever;

public void display() {
    if (obsever == null) {
        obsever = new MyImageObsever(this);
    }
    g2.setColor(Color.yellow);
    g2.fillRect(0, 0, pain.getWidth(), pain.getHeight());
    g2.drawImage(img, 0, 0, obsever);
    pain.repaint();
}

public class MyImageObsever implements ImageObserver {

    private RTester tester;

    public MyImageObsever(RTester tester) {
        this.tester = tester;
    }

    @Override
    public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) {
        tester.display();
        return (infoflags & (ALLBITS|ABORT)) == 0;
    }

}