Question

So I have never used Swing Worker at all, but I heard it was a good way to load images because it allows for images to be processed in the background from what I believe. In the process of trying to implement it I ran into a problem where the image isn't draw. I don't have any errors, but the screen just seems white. Can anybody take a look at my code and tell me where it's going wrong?

    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Image;
    import java.awt.Toolkit;
    import java.io.IOException;
    import java.net.URL;
    import javax.imageio.ImageIO;
    import javax.swing.Icon;
    import javax.swing.ImageIcon;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingWorker;

    public class Screen extends JPanel{
    //Screen Vairables
    public static JFrame frame = new JFrame("Soul Voyage");
    public Dimension size = new Dimension((int)Toolkit.getDefaultToolkit().getScreenSize().width,(int)Toolkit.getDefaultToolkit().getScreenSize().height);
    Graphics draw;

    public Screen(){            
        //Screen Creation            
        frame.setSize(size);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.setVisible(true);            
        //Other
    }

    @Override
    public void paintComponent(Graphics g){
        draw = g;
        super.paintComponent(g);
        new ImageLoader().execute();
        g.dispose();
    }

    public static void main(String[] args) {
        Screen s = new Screen();
        frame.add(s);
    }

    class ImageLoader extends SwingWorker{

        private ImageIcon image;

        @Override
        protected Icon doInBackground() throws IOException {                
            Image picture = ImageIO.read(new URL("Background.jpg"));
            image = new ImageIcon(picture);
            image.paintIcon(frame, draw, size.width, size.height);
            return image;
        }            
    }
}
Was it helpful?

Solution

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();
            }
        }           
    }
}

OTHER TIPS

never used Swing Worker at all, but I heard it was a good way to load images because it allows for images to be processed in the background

Java could read images asynchronously since the Toolkit in Java 1.1.

If added to an ImageObserver such as a JPanel, a repaint() will be invoked when there is more of the image to draw. Load progress can be monitored using a MediaTracker.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top