如何在Swing应用程序中在后台加载图像?

时间:2014-11-17 19:03:09

标签: java swing awt

我有一个在Windows上以全屏模式运行的简单Swing / AWT应用程序。我有几个不同的PNG文件,它根据上下文加载为自己的背景图像。

它像这样加载它们:

BufferedImage bufferedImage;
bufferedImage = ImageIO.read(getClass().getResource("/bg1.png"));
Image bgImage1 = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
bufferedImage = ImageIO.read(getClass().getResource("/bg2.png"));
Image bgImage2 = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);
bufferedImage = ImageIO.read(getClass().getResource("/bg3.png"));
Image bgImage3 = bufferedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH);

后来把它们画成这样:

window.repaint();
graphics.drawImage(bgImage1, 0, 0, null);
// draw some other stuff too, like text

为了彻底,windowJWindow变量,graphicsGraphics2D变量。

当我将一张背景图片换成另一张背景图片时,我遇到的问题就发生了。我第一次进行切换时,调用这样的东西:

window.repaint();
graphics.drawImage(bgImage2, 0, 0, null);
// draw some other stuff too, like text

......整个屏幕变白了大约一秒钟。然后它确实成功显示了图像,但闪烁真的很烦人。我的猜测是,因为图像相对较大且分辨率较高(2560x1440),所以需要大约一秒钟来加载它们并将它们缩放到合适的大小。

如何让它静静加载这些图像?如...在第一次显示新的背景图像时,如何避免画一个空白的白色屏幕?随后的所有时间都已经是瞬间的,可能是因为它在那时真正抓住了它们。但是简单地调用getScaledInstance显然不足以将内容放入内存中,因为在我调用drawImage之前它实际上并没有闪烁。

2 个答案:

答案 0 :(得分:2)

ImageIcon将作为功能在后台加载。

您也可以使用后台线程轻松完成此操作,例如:

final String path = "/example.png";
new SwingWorker<BufferedImage, Void>() {
    @Override
    public BufferedImage doInBackground() throws IOException {
        return ImageIO.read(ClassName.class.getResource(path));
    }
    @Override
    public void done() {
        try {
            BufferedImage img = get();
            // put img somewhere
        } catch(InterruptedException ignored) {
        } catch(ExecutionException ex) {
            ex.printStackTrace(System.err);
        }
    }
}.execute();

此外,

window.repaint();
graphics.drawImage(bgImage2, 0, 0, null);

这让我有点担心。通常,我们不需要请求整个顶级容器的repaint。您也不应该使用getGraphics()来绘画。

非顶级Swing组件是双缓冲的,但如果你在绘画结构之外绘画,你就不会得到它。它会导致闪烁。

正确定制绘画的两个好消息来源是:

绘画应该通过覆盖JComponent上的paintComponent来被动地完成。 JLabel还可以将ImageIcon显示为一项功能,因此如果您只想显示图像,则无需进行自定义绘制。

答案 1 :(得分:0)

我注意到缩放需要花费大量时间,而不是加载图像。 因此,我通常存储缩放的图像,以便稍后使用它,所以我只需要缩放一次。