On my new HD screen with Windows 11, it is indispensable to set the display settings to 125% to be able to read text, but the icons are getting resized too. I don't get this default behaviour of enlarging icons that can't be enlarged. Obviously it can't look good once resized. I wrote a workaround with CustomMultiResolutionImage to put some transparent padding instead of enlarging the images. It worked for me on 2 of the icons "newFolder" and "upFolder" of the JFileChooser, but not on "viewMenu".
import java.awt.Image;
import java.awt.image.BaseMultiResolutionImage;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.stream.Stream;
import javax.imageio.ImageIO;
import javax.swing.*;
public class Main {
static {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
Stream.of("newFolder", "upFolder", "viewMenu").forEach(Main::adaptFileChooserIconKey);
}
private static void adaptFileChooserIconKey(String shortKey) {
String key = getFileChooserIconKey(shortKey);
if (UIManager.get(key) instanceof ImageIcon imageIcon) {
UIManager.put(key, new ImageIcon(new CustomMultiResolutionImage(imageIcon.getImage())));
}
}
private static String getFileChooserIconKey(String shortKey) {
return "FileChooser." + shortKey + "Icon";
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new JFileChooser().showOpenDialog(new JFrame());
});
}
static class CustomMultiResolutionImage extends BaseMultiResolutionImage {
private static final int DEFAULT_IMAGE_COUNT = 10;
public CustomMultiResolutionImage(Image baseImage, int imageCount) {
super(createLargerImages(baseImage, imageCount));
}
public CustomMultiResolutionImage(Image baseImage) {
this(baseImage, DEFAULT_IMAGE_COUNT);
}
public CustomMultiResolutionImage(String iconPath) throws IOException {
this(iconPath, DEFAULT_IMAGE_COUNT);
}
public CustomMultiResolutionImage(String iconPath, int imageCount) throws IOException {
this(ImageIO.read(CustomMultiResolutionImage.class.getResource(iconPath)), imageCount);
}
private static Image[] createLargerImages(Image baseImage, int imageCount) {
int baseWidth = baseImage.getWidth(null);
int baseHeight = baseImage.getHeight(null);
Image[] images = new Image[imageCount + 1];
images[0] = baseImage;
for (int i = 1; i < images.length; i++) {
images[i] = new BufferedImage(baseWidth + 2 * i, baseHeight + 2 * i, BufferedImage.TYPE_INT_ARGB);
images[i].getGraphics().drawImage(baseImage, i, i, null);
}
return images;
}
@Override
public Image getResolutionVariant(double destImageWidth, double destImageHeight) {
return super.getResolutionVariant(Math.round(destImageWidth), Math.round(destImageHeight));
}
}
}