【问题标题】:Swings ImageIcon constructor is very slowSwings ImageIcon 构造函数很慢
【发布时间】:2014-01-20 10:41:15
【问题描述】:

编辑:有关此问题的答案,请参阅此答案的 cmets。 TLDR:瓶颈是缩放图像,但分析显示这是 ImageIcon 构造函数中的一个问题。


$ java -version
Picked up _JAVA_OPTIONS: -Dswing.aatext=true -Dawt.useSystemAAFontSettings=on
java version "1.7.0_45"
OpenJDK Runtime Environment (IcedTea 2.4.3) (ArchLinux build 7.u45_2.4.3-1-x86_64)
OpenJDK 64-Bit Server VM (build 24.45-b08, mixed mode)

我的应用程序在启动时会加载 1,380 个图标。加载代码如下所示。使用 SSD 磁盘,ImageIcon 构造函数调用实际上比磁盘读取更昂贵(磁盘读取可能会使用一些缓存..)

加载图标需要5.4s,其中3.2s用在ImageIcon构造函数中。

有没有办法加快 ImageIcon 的构建或使用其他方法?

private ImageIcon setIcon(LogicalIcon iconInfo, int size) {
    ImageIcon icon = iconImages.get(iconInfo.getIconName());
    if(icon == null) {
        BufferedImage image = null;
        try {
            image = ImageIO.read(getBestPreviewIcon(iconInfo).getFile());
            icon = new ImageIcon(ImageUtils.scaleDownTo(image, new Dimension(size, size)));
            iconImages.put(iconInfo.getIconName(), icon);
        } catch (IOException e) {
            // FIXME: Add a "Missing Image" icon
            e.printStackTrace();
        }
    }
    setIcon(icon);
    return icon;
}

【问题讨论】:

  • 重采样需要时间;尝试不缩放。
  • 您在考虑调用 scaleDownTo 吗?我也预计这是问题所在,但根据 NetBeans 分析器,这仅占 9 毫秒。可能是 Image 类使用了一些后期绑定,所以在请求之前它实际上并没有完成。我会检查的。编辑:是的,禁用缩放完全消除了瓶颈..我想我毕竟需要添加一个加载屏幕..以及选择缩放质量的设置..
  • 是的,我可以在显示进度条时使用它。应用程序的唯一目的是选择图标,所以在加载图标之前没有用。

标签: java performance swing


【解决方案1】:

为了缓解观察到的延迟,请在SwingWorker 的后台线程中加载图像并重新采样。您可以在每个可用时 publish() 将其添加到 List<Image> 在您的 process() 实现中。可以选择和操作最初加载的图像,而其余的正在加载。让进度指示器监听属性变化。相关示例见herehere

总结 cmets 的附录:

  • 工作线程可以增强用户对活跃度的感知。

  • 一开始就知道图像的数量可以让进度指示器的粒度更细。

  • 针对瓶颈,scaleDownTo()方法出现调用getScaledInstance();有关详细信息,请参阅The Perils of Image.getScaledInstance(),并考虑检查herehere 的替代方案。

【讨论】:

  • 感谢您的提示。应用程序的主要工作是过滤一组图标,因此如果您可以在不显示所有图标的情况下开始使用它,那将非常令人困惑。我想我会暂时保持原样。给出错误问题的好答案:)
  • 看起来很合理,但用户可能比“死”时间更能容忍“实时”等待。如果您一开始就知道图标的数量,则可以在进度指示器中显示更精细的粒度。
  • 我同意。在我的计算机上启动需要 6.7 秒,但我希望应用程序在打开后可以使用几分钟。如果需要,我可以显示一个非常精确的进度条。我需要考虑一种不混淆的处理方式。自 6 个月前发布以来,我们没有收到任何关于该应用程序运行缓慢的报告,但话又说回来......我们根本没有得到太多反馈:/
  • 你也可以看看ImageUtils.scaleDownTo()的实现;检查替代方案herehere
  • 啊,很高兴知道。 scaleDownTo 在计算新大小后使用 Image.getScaledInstance。很高兴看到我有一些选择。
猜你喜欢
  • 2020-10-03
  • 2010-09-15
  • 2017-06-11
  • 2011-12-19
  • 2010-12-11
  • 2018-01-23
  • 2020-12-22
  • 1970-01-01
相关资源
最近更新 更多