英文:
Use BaseMultiResolutionImage-backed IconImage in HTML img tag
问题
我们从类资源中创建了一系列的 BufferedImage 对象,这些对象代表了不同尺寸的同一图标的变体。我们将它们传递给 BaseMultiResolutionImage 并从中创建了一个多尺寸的 ImageIcon,然后可以将其用作任何图标的替代品(在 Java 9+ 中),并且在各种 Swing 组件上作为图标(例如:通过 JLabel.setIcon(Icon)
)放置时会自动调整大小,而在 HiDPI 屏幕上不会有太多的质量损失。
在迁移到这种 ImageIcons 之前,我们只是简单地使用 someIcon = new ImageIcon(SomeClass.getResource(String))
从类资源中获取图标。这使我们能够在用于填充例如 JLabel 文本的 HTML 内容中引用相关联的图像(如此处所述:链接):
new JLabel("<html>图标在<img src=\"" + someIcon.getDescription() + "\"/>中间</html>");
这可以工作,因为 ImageIcon
构造函数接受资源的 URL,并将其设置为 ImageIcon 对象的描述。显然,这不再起作用,因为现在使用了不同的构造函数,而且每个 ImageIcon 现在可以有多个关联的资源 URL,没有办法知道在运行时将使用哪个URL。
是否有一种方式可以在 Swing 组件的 HTML <img>
标签中引用多尺寸的 ImageIcon 实例,以便可以自动选择正确的图像,就像将同一对象设置为 JLabel 对象的图标时一样?
以下是伪代码,用于创建我们想要在 HTML 中引用的 ImageIcon 对象(假设存在一些 PNG 文件作为资源且使用了 Java 9+):
package org.stackoverflow;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MultiResIconTest extends JFrame {
public MultiResIconTest() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("MultiResIconTest");
setLayout(new BorderLayout());
JLabel label = new JLabel("some label");
try {
ImageIcon icon = createMultiResIcon(); // 我们能在 img src 属性中引用这个对象吗...
label.setIcon(icon); // ...以便它可以像这样工作吗?
} catch (IOException ex) {
ex.printStackTrace();
}
add(label);
setSize(640, 380);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new MultiResIconTest().setVisible(true);
}
});
}
private ImageIcon createMultiResIcon() throws IOException {
BufferedImage base = ImageIO.read(MultiResIconTest.class.getResource("icon.png"));
BufferedImage first = ImageIO.read(MultiResIconTest.class.getResource("icon@1.25x.png"));
BufferedImage second = ImageIO.read(MultiResIconTest.class.getResource("icon@1.5x.png"));
BufferedImage third = ImageIO.read(MultiResIconTest.class.getResource("icon@1.75x.png"));
BufferedImage fourth = ImageIO.read(MultiResIconTest.class.getResource("icon@2x.png"));
Image[] images = new Image[] {base, first, second, third, fourth};
Image multiImage = new java.awt.image.BaseMultiResolutionImage(images);
return new ImageIcon(multiImage);
}
}
英文:
We create a bunch of BufferedImage objects from class resources that represent variants of the same icon in different sizes, pass that to BaseMultiResolutionImage and create a multi-sized ImageIcon from it, which may then be used as a drop in replacement for any icon (on Java 9+) and that resizes automatically when placed as an icon on various Swing components (eg.: via JLabel.setIcon(Icon)
) without much quality loss on HiDPI screens.
Before migrating to such ImageIcons, we simply used someIcon = new ImageIcon(SomeClass.getResource(String))
to obtain the icons from class resources. This provided us with the ability to reference the associated images in HTML content used to populate for example a JLabel's text (as described here):
new JLabel("<html>Icon in <img src=\"" + someIcon.getDescription() + "\" /> the middle</html>");
This worked because the ImageIcon
constructor took the URL of the resource and set it as the description of the ImageIcon object. It obviously no longer works, since a different constructor is now used, besides each ImageIcon may now have several resource URLs associated with it, with no way of knowing which will be actually used at runtime.
Is there a way to reference multi-sized ImageIcon instances in Swing component HTML <img>
tag, so that the proper image is auto-selected, as for example, when the same object is set as an icon for a JLabel object?
Here's the pseudo-code that creates an ImageIcon object we'd like to reference in HTML (assumes presence of some PNG files as resources and Java 9+):
package org.stackoverflow;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class MultiResIconTest extends JFrame {
public MultiResIconTest() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("MultiResIconTest");
setLayout(new BorderLayout());
JLabel label = new JLabel("some label");
try {
ImageIcon icon = createMultiResIcon(); // Can we reference this object in an img src attribute...
label.setIcon(icon); // ...so it works like this?
} catch (IOException ex) {
ex.printStackTrace();
}
add(label);
setSize(640, 380);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new MultiResIconTest().setVisible(true);
}
});
}
private ImageIcon createMultiResIcon() throws IOException {
BufferedImage base = ImageIO.read(MultiResIconTest.class.getResource("icon.png"));
BufferedImage first = ImageIO.read(MultiResIconTest.class.getResource("icon@1.25x.png"));
BufferedImage second = ImageIO.read(MultiResIconTest.class.getResource("icon@1.5x.png"));
BufferedImage third = ImageIO.read(MultiResIconTest.class.getResource("icon@1.75x.png"));
BufferedImage fourth = ImageIO.read(MultiResIconTest.class.getResource("icon@2x.png"));
Image[] images = new Image[] {base, first, second, third, fourth};
Image multiImage = new java.awt.image.BaseMultiResolutionImage(images);
return new ImageIcon(multiImage);
}
}
专注分享java语言的经验与见解,让所有开发者获益!
评论