2

所以我从来没有使用过 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;
        }            
    }
}
4

2 回答 2

4

SwingWorker在后台运行,在一个单独的Thread,所以做类似...

new ImageLoader().execute();

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

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

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

现在,使用 a 的原因之一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();
            }
        }           
    }
}
于 2013-09-21T02:26:00.377 回答
2

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

Toolkit从Java 1.1 开始,Java 可以异步读取图像。

如果添加到ImageObserver诸如 a JPanelrepaint()当有更多图像要绘制时将调用 a 。可以使用MediaTracker.

于 2013-09-21T11:31:13.747 回答