SwingWorker
runs in the background, in a separate Thread
, so doing something like...
new ImageLoader().execute();
Basically says, do this and I will continue running...It won't wait for worker to complete.
You really shouldn't be loading images in paintXxx
methods anyway...and don't dispose
of resources you did not explicitly create (ie g.dispose()
is a bad idea) and draw = g;
worries me, you shouldn't be trying to maintain a reference to any Graphics
context you did not explicitly create...
Instead, you should pass some kind of callback to the SwingWorker
, so when it's done, it knows who to notify.
Now, one of the reasons to use a SwingWorker
is because it has functionality to allow you to more easily synchronise the background process with the Event Dispatching Thread, making it safer to interact with the UI without fear of generating dirty paints or dead locked threads :P
For example...
public interface ImageConsumer {
public void imageLoaded(BufferedImage img);
}
public class Screen extends JPanel implements ImageConsumer {
/*...*/
private BufferedImage img;
public Screen(){
new ImageLoader(this).execute();
}
/*...*/
public void imageLoaded(BufferedImage img) {
this.img = img;
repaint();
}
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
protected class ImageLoader extends SwingWorker<BufferedImage, BufferedImage> {
private ImageConsumer consumer;
public ImageLoader(ImageConsumer consumer) {
this.consumer = consumer;
}
@Override
protected BufferedImage doInBackground() throws IOException {
BufferedImage picture = ImageIO.read(new URL("Background.jpg"));
return picture;
}
protected void done() {
try {
BufferedImage img = get();
consumer.imageLoaded(img);
} catch (Exception exp) {
exp.printStackTrace();
}
}
}
}