Reputation: 1295
I need some help with painting an Image object upon/inside/on a BufferedImage and then painting that BufferedImage on a JPanel.
I've prepared a small program to illustrate my problem. Just a frame with a panel accompanied by an ImageLoader.
The image is placed in the same folder as the code. The sten Image is painted successfully when just painted, but not when I try painting it with the BufferedImage, which you'll notice if you try to run the program. just create the Test object and the constructor does the rest.
Thanks in advance!
My code:
public class Test extends JFrame{
static class ImageLoader {
public static Image loadImage(String name){
Image img = null;
img = Toolkit.getDefaultToolkit().getImage(ImageLoader.class.getResource(name));
return img;
}
}
class Panel extends JPanel{
Image sten;
BufferedImage bf = new BufferedImage(500,500,BufferedImage.TYPE_INT_RGB);
public Panel(Image sten){
super();
this.sten = sten;
initBF();
}
private void initBF(){
Graphics2D g = (Graphics2D) bf.createGraphics();
g.drawImage(sten, 0,0,this);
}
public void paintComponent (Graphics g)
{
g.drawImage(bf, 100,100,null);
g.drawImage(sten, 0,0,null);
repaint();
}
}
public Test(){
setSize(new Dimension(500, 500));
setEnabled(true);
this.setBounds(50, 150, 500, 500);
setVisible(true);
Image sten = ImageLoader.loadImage("sten.png");;
Panel panel = new Panel(sten);
panel.setBackground(Color.GREEN);
panel.setSize(500, 500);
this.add(panel);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel.paintComponent(this.getGraphics());
}
}
Upvotes: 0
Views: 455
Reputation: 159774
The problem is that Toolkit.getDefaultToolkit().getImage
loads images asychronously so will not be loaded when paintComponent
is invoked. Use a MediaTracker
to block until the image has been loaded:
public Image loadImage(String name) {
Image img = null;
MediaTracker tracker = new MediaTracker(myPanel); // pass the panel from ctor
img = Toolkit.getDefaultToolkit().getImage(ImageLoader.class.getResource(name));
tracker.addImage(img, 0);
try {
tracker.waitForID(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
return img;
}
or far simpler:
img = ImageIO.read(ImageLoader.class.getResource(name)));
This will eliminate the need to use MediaTracker
.
Some notes:
paintComponent
directly, request repaints by invoking repaint
.getGraphics
for custom painting - this uses a transient Graphics
reference.Graphics
reference, make sure to call Graphics#dispose
when finished using the reference.Upvotes: 1
Reputation: 75906
In addition of Reimeus' aswer, notice that Toolkit.getDefaultToolkit().getImage()
is non-blocking, it loads images asynchronously, so at the point when you call g.drawImage(sten, 0,0,this);
sten
will probably not still actually be loaded (see the doc of the method). See also this (false) bug report.
Upvotes: 1