Java has famously tried to sell the world of software development on the idea of Write Once Run Anywhere (WORA). Unfortunately that doesn’t work in practice, especially when you’re writing GUI applications using the stock Java release. I was reminded of this yet again when I tried for something very basic; code that would run on all platforms and return an icon resource, in this case a close button that would work across all platforms and look like it fit in with the rest of the environment.
I went looking for a close icon I could use on a button that matched the given look-and-feel. I used the following call to UIManager:
It worked beautifully on Windows 8.1, and Windows 7. I was happy until I tried to run it on three different Linux distributions, and two versions of one of the three. Instead of getting a reasonable displayable icon, I got nothing. Not a null, not an exception, nothing. Specifically, I got a transparent icon that didn’t show up on the Java UI, but never the less took up the required space. When this first happened I thought my code was at fault, until I wrote a very short routine to dump all the internal look-and-feel references and what they returned, as strings. For Windows, I got the following:
InternalFrame.closeIcon = com.sun.java.swing.plaf.windows.WindowsIconFactory$FrameButtonIcon@4f626d85
For Linux (specifically CentOS (RHEL) 6.5) I got the following:
InternalFrame.closeIcon = javax.swing.plaf.basic.BasicIconFactory$EmptyFrameIcon@492ee972
Yes, I got an EmptyFrameIcon. I went looking to see if I could find anything under all the locations that Linux likes to store icons, but found nothing I could consistently use. In the end I went back to drawing on the button face (which I’ll give an example of shortly), since all I wanted was essentially the ‘X’ that appears all over.