I can confirm that the scaling your images works with on Oracle Java 1.8. I cannot get the NSImage
hack to work on java 1.7 or 1.8. I think this only works with Java 6 from Mac...
Unless someone else has a better solution, what I do is the following:
Create two sets of icons.
If you have a 48pixel
width icon create one 48px
@normal DPI
and another at 96px
with 2x DPI
. Rename the 2xDPI
image as @2x.png
to conform with apple naming standards.
Subclass ImageIcon
and call it RetinaIcon
or whatever.
You can test for a Retina display as follows:
public static boolean isRetina() {
boolean isRetina = false;
GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
try {
Field field = graphicsDevice.getClass().getDeclaredField("scale");
if (field != null) {
field.setAccessible(true);
Object scale = field.get(graphicsDevice);
if(scale instanceof Integer && ((Integer) scale).intValue() == 2) {
isRetina = true;
}
}
}
catch (Exception e) {
e.printStackTrace();
}
return isRetina;
}
Make sure to @Override
the width and height of the new ImageIcon
class as follows:
@Override
public int getIconWidth()
{
if(isRetina())
{
return super.getIconWidth()/2;
}
return super.getIconWidth();
}
@Override
public int getIconHeight()
{
if(isRetina())
{
return super.getIconHeight()/2;
}
return super.getIconHeight();
}
Once you have a test for the retina screen and your custom width/height methods overridden you can customise the painIcon
method as follows:
@Override
public synchronized void paintIcon(Component c, Graphics g, int x, int y)
{
ImageObserver observer = getImageObserver();
if (observer == null)
{
observer = c;
}
Image image = getImage();
int width = image.getWidth(observer);
int height = image.getHeight(observer);
final Graphics2D g2d = (Graphics2D)g.create(x, y, width, height);
if(isRetina())
{
g2d.scale(0.5, 0.5);
}
else
{
}
g2d.drawImage(image, 0, 0, observer);
g2d.scale(1, 1);
g2d.dispose();
}
I do not know how this will work with multiple screens though- is there anyone else that can help out with that???
Hope this code helps out anyway!
Jason Barraclough.
Here is an example of using the scaling as mentioned above:
RetinaIcon is on the left. ImageIcon is on the right