使用Swing Worker加载图像

时间:2013-09-21 02:08:50

标签: java swing swingworker worker

所以我从来没有使用过Swing Worker,但是我听说这是加载图像的一种好方法,因为它可以让我在相信的背景下处理图像。在尝试实现它的过程中,我遇到了一个图像没有绘制的问题。我没有任何错误,但屏幕看似白色。任何人都可以查看我的代码并告诉我哪里出错了?

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

2 个答案:

答案 0 :(得分:3)

SwingWorker在后​​台运行,在单独的Thread中运行,所以做类似的事情......

new ImageLoader().execute();

基本上说,这样做,我会继续跑...它不会等待工人完成。

你真的不应该用paintXxx方法加载图像......并且不要dispose你没有明确创建的资源(即g.dispose()是一个坏主意)并且draw = g;让我担心,你不应该试图保持对你没有明确创建的任何Graphics上下文的引用......

相反,你应该将某种回调传递给SwingWorker,所以当它完成后,它知道要通知谁。

现在,使用SwingWorker的原因之一是因为它具有允许您更轻松地将后台进程与事件调度线程同步的功能,使得与UI交互更安全而不用担心生成脏的油漆或死锁线:P

例如......

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

答案 1 :(得分:2)

  

从来没有使用过Swing Worker,但我听说这是加载图片的好方法,因为它允许在后台处理图像

Java可以自Java 1.1中的Toolkit异步读取图像。

如果添加到JPanel repaint(),则会在需要绘制更多图片时调用{{1}}。可以使用ImageObserver监控加载进度。