JavaFX 2.2是否支持.ico格式的图片?

8
我正在开发一个必须具有自定义图标的应用程序。提供的图标在所有尺寸(256x256、48x48、32x32)中都相同,只有16x16的图标被简化了。
我考虑使用.ico格式(可以存储所有不同的图标,并让操作系统显示最佳图标),但它似乎不受javafx.scene.image支持(我没有找到任何确认信息)。
以下是我设置图标的方法。
stage.getIcons().add(new Image(getClass().getResourceAsStream("/path/to/icon.ico")));

在这种情况下,图标永远不会显示。如果我将此图标转换为 .png 图像,则可以正常工作,但是强制始终显示相同的图标(即使在 16x16 中)。
在 JavaFX 2.2 中是否有一种方法可以显示 .ico(即使是 hacky 方式),还是必须使用其他图像格式?
更新
我将我的 .ico 分成多个 png(每个尺寸一个),然后逐个加载它们。
stage.getIcons().add(new Image(getClass().getResourceAsStream("/path/to/icon_16x16.png")));
stage.getIcons().add(new Image(getClass().getResourceAsStream("/path/to/icon_256x256.png")));

256x256和16x16是两个不同的图片,但16x16从未在应用程序的左上角显示(尽管这是最接近的大小)。
3个回答

9

功能请求

请参阅相关的功能请求:

该功能目前未分配到任何版本中,但如果您喜欢,可以投票或发表评论。

使用第三方库加载ico文件

与此同时,您可以使用各种实用程序创建 java.awt.image.BufferedImage 格式的图标,然后使用 SwingFXUtils 将它们转换为 JavaFX。haraldK 在他的回答中提供了这种方法的示例。另一个例子是 Willow 浏览器的 fav 图标获取器,它使用 image4j 库,不过 haraldK 的 twelve monkeys 库可能更好。您的另一个选择是将基于 awt 的图标库源代码移植到 JavaFX,并利用 WritableImage

建议

您不使用 png 的原因是它总是显示 16x16,这让我感到有些奇怪,因为 stage.getIcons() 文档返回一个可以添加到的图像列表(您不限于添加单个图标)。从 javadoc 中可以看出:

获取在窗口装饰和最小化时要使用的图标图像。这些图像应该是同一图像的不同大小,将选择最佳大小,例如 16x16、32x32。

其他问题

如果根据大小,图像并不总是相同的呢?

提供不同大小的图像可能是可以接受的。如果系统插值提供的图像以创建未提供的图标大小,那可能会导致问题 - 但我认为系统很难这样做。 "图像应该是同一图像的不同大小" 更多的是指南而不是实际规则。如果您需要不同大小的不同图像,请尝试提供多个 png 图像并查看会发生什么。


+1 提到了可以只使用多个PNG文件(这通常是我们所做的)。不过我已经投票了,所以不能再给你额外的分数...;-) PS:为什么Kenai JIRA受到密码保护? - Harald K
@haraldK 这不仅仅是密码保护。它只需要您在阅读/发布任何内容之前先注册。尽管如此,强制要求进行阅读访问并没有意义。 - ItachiUchiha
@jewelsea 使用这种方法,所有图像应该是相同的图像(但具有不同的尺寸)。如果根据尺寸,图像并不总是相同的呢? - Spotted
2
@jewelsea 我尝试提供不同尺寸的多个图像,但是行为有点奇怪:所选图像似乎总是最大的(必要时缩小)。 - Spotted

5
我认为JavaFX不直接支持ICO格式。我非常确定它只支持JPEG、GIF和PNG格式,但我还没有找到官方来源来证实这一点。
然而,你可以使用我的ICO插件来读取ICO文件,并使用SwingFXUtils.toFXImage(bufferedImage, null)将图像转换为FX中的Image
请注意,读取器只是按照ICO文件中找到的顺序返回图标,所以ImageIO.read(...)不会给你想要的图标(它只会读取第一个)。相反,你需要读取每个图标,转换并添加到你的舞台上。FX会为你选择正确的大小。:-)
类似这样:
ImageInputStream stream = ImageIO.createImageInputStream(getClass().getResourceAsStream("/path/to/icon.ico"));
ImageReader reader = ImageIO.getImageReaders(stream).next();

reader.setInput(stream);
int count = reader.getNumImages(true);

List<Image> fxImages = new ArrayList<>(count);

for (int i = 0; i < count; i++) {
    BufferedImage bufferedImage = reader.read(i, null);
    Image fxImage = SwingFXUtils.toFXImage(bufferedImage, null);
    fxImages.add(fxImage);
}

stream.close(); // Remember to close/dispose in a finally block
reader.dispose();

// ...

stage.getIcons().addAll(fxImages);

1
我已经为你的答案点赞,但最终我会选择使用多个预先计算好的PNG文件,而不是在每次执行时进行计算。 - Spotted
@Spotted 我理解。 :-) - Harald K

1
使用 image4j
ArrayList<Image> lImages = new ArrayList<>();
ICODecoder.read(Global.FILE_ICON).stream().forEach((lBufferedImage) -> lImages.add(SwingFXUtils.toFXImage(lBufferedImage, null)));
this.getStage().getIcons().addAll(lImages);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接