I can confirm that scaling your images works on Oracle Java 1.8. I cannot hack NSImage to work with java 1.7 or 1.8. I think this only works with Java 6 with Mac ...
If anyone else has a better solution, I do the following:
Create two sets of icons. If you have a 48pixel wide 48pixel , create one 48px @normal DPI and the other at 96px using 2x DPI . Rename the 2xDPI image as @2x.png to meet Apple's naming standards.
Subclass ImageIcon and name it RetinaIcon or whatever. You can check the 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 @Override width and height of the new ImageIcon class:
@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 are overridden, you can set up 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, although is there anyone who can help with this?
Hope this code helps anyway!
Jason Barracklow.
Here is an example of using scaling as described above: RetinaIcon is on the left. ImageIcon is on the right