JavaFX 2.2 Поддержка изображений.ico?
Я разрабатываю приложение, которое должно иметь собственный значок. Предоставленный значок одинаков во всех размерах (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 (даже в хакерской манере) или мне нужно использовать другие форматы изображений?
Обновить
Я разделил свой.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 ответа
Запрос функции
Смотрите запрос связанной функции:
В настоящее время эта функция не относится к релизу, но вы можете проголосовать или прокомментировать ее, если хотите.
Загрузка файлов ico с использованием сторонних библиотек
В то же время, вы можете использовать различные утилиты для создания иконок в java.awt.image.BufferedImage
форматировать и затем конвертировать их в JavaFX, используя SwingFXUtils
, haraldK приводит пример такого подхода в своем ответе. Другим примером является сборщик иконок fav для браузера ивы, который использует библиотеку image4j, хотя библиотека из двенадцати обезьян haraldK, вероятно, лучше использовать. Другой вариант - перенести исходный код одной из библиотек значков на основе awt в JavaFX, используя WritableImage
,
Совет
Ваше рассуждение о том, что png не используется, потому что он всегда отображает 16x16, немного странно для меня, потому что stage.getIcons()
Документация возвращает список изображений, к которым вы можете добавить (вы не ограничены добавлением одного значка). Из Javadoc:
Получает изображения значков, которые будут использоваться в оформлении окон и при сворачивании. Изображения должны быть разных размеров одного и того же изображения, и будет выбран лучший размер, например. 16х16, 32,32.
Дополнительный вопрос
Что делать, если в зависимости от размера изображение не всегда одинаково
Вероятно, нормально предоставлять разные изображения. Если система интерполирует предоставленные изображения для создания значков не предоставленных размеров, это может вызвать проблему, но я думаю, что система вряд ли это сделает. "Изображения должны быть разных размеров одного и того же изображения" - это скорее ориентир, чем фактическое правило. Если вам нужны разные изображения разных размеров, попробуйте предоставить несколько изображений PNG для этого и посмотрите, что произойдет.
Я не думаю, что JavaFX напрямую поддерживает формат ICO. Я уверен, что список только JPEG, GIF и PNG, но я еще не нашел официальный источник, который подтверждает это.
Тем не менее, вы можете использовать мой плагин ICO для ImageIO, чтобы прочитать файл ICO и преобразовать изображение в FX Image
с помощью SwingFXUtils.toFXImage(bufferedImage, null)
,
Обратите внимание, что читатель просто возвращает значки в том порядке, в котором они находятся в файле 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);
Используйте 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);