The FileIcon
is an abstract class creates a javax.swing.Icon
for a File
.
A file icon is a small (usually about 16x16) icon you can place next to a file name. Usually all files with the same file extension share the same file icon.
An "icon" is different from a "thumbnail". (A thumbnail is an image that is a rendering of a specific file.) And sometimes the word "preview" also carries special implications of interactivity (for ex: a video). So "icon", "thumbnail" and "preview" are all separate buzzwords.
The simplest one-line invocation resembles:
Icon icon = FileIcon.get().getIcon(file);
Each subclass is responsible for deciding how to identify the appropriate icon. And the FileIcon
class has a static getter/setter method for maintaining the active default FileIcon
on a given system.
There are currently 2 subclasses of FileIcon
. (There used to a 3rd that involved reflection, but in accordance with Java guidelines I'm trying to phase out reflection.)
This implementation uses FileSystemView
, and it resembles:
public class FileSystemViewFileIcon extends FileIcon { @Override public Icon getIcon(File file) { FileSystemView fsv = FileSystemView.getFileSystemView(); Icon icon = fsv.getSystemIcon(file); if (icon != null) return icon; return super.getDefaultIcon(file); } }
This looks like it should be the ideal way to go, because it's so clean/direct. But on Mac it only ever returns a generic file or folder icon. I tried rummaging through the source code for FileSystemView
(and related classes) to see if I could modify (hack) it without reflection, but there aren't a lot of entry points.
This implementation uses a JFileChooser's
FileView
, and it resembles:
public class FileViewFileIcon extends FileIcon { FileView fileView; public FileViewFileIcon() { JFileChooser chooser = new JFileChooser(); fileView = chooser.getUI().getFileView(chooser); } @Override public Icon getIcon(File file) { return fileView.getIcon(file); } }
I don't like that this is so indirect and clunky. Sometimes creating a JFileChooser
is not trivially cheap, either. But on Mac: this works great. It returns scalable icons for most every file type.
On Windows: both this approach and the FileSystemView
approach produce unscaleable (kind of crappy/pixelated) 16x16 icons. But today as I wrote this I saw emails trickle in about a pull request to update this in future Java versions, so that's exciting.
This demo includes an option to scale the icon.
On Mac the icons we get back are high-resolution, so they can scale to most any size with great clarity.
On Windows the icons are not (yet) high-resolution. (Although in a future Java release that should change.) So if you want a universal cross-platform approach: you ought to just stick with the icon's default size. (And even that, unfortunately, will look pixelated on a high-resolution monitor on Windows.)