使用 Swing 工作线程加载图像



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

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

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

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

自Java 1.1 Toolkit以来,Java可以异步读取图像。

如果添加到ImageObserver(如JPanel)中,当有更多的图像要绘制时,将调用repaint()。 可以使用MediaTracker监控加载进度。

最新更新