Windows 8 Distorts my TrayIcon

2019-04-21 07:22发布

问题:

Windows 8 appears to make tray icons be 20 x 20 pixels. It seems as though Java still thinks they should be 16 x 16 pixels. This is causing some bad distortion as Java scales things down, and then Windows scales things back up. The following example uses these three images to create three tray icons that look like this (note the distortion):

.

import java.awt.Image;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;

public class TrayTest
{
    public static void main(String[] args) throws Exception
    {
        final SystemTray tray = SystemTray.getSystemTray();

        TrayIcon trayIcon16 = new TrayIcon(getImage("16pxBlue.png"));
        tray.add(trayIcon16);

        TrayIcon trayIcon20 = new TrayIcon(getImage("20pxRed.png"));
        tray.add(trayIcon20);

        TrayIcon trayIcon20autoSize = new TrayIcon(getImage("20pxGreen.png"));
        trayIcon20autoSize.setImageAutoSize(true);
        tray.add(trayIcon20autoSize);
    }

    public static Image getImage(String resource)
    {
        return Toolkit.getDefaultToolkit().createImage(TrayTest.class.getResource(resource));
    }
}

This is what the whole thing looks like magnified with pixel lines added (opening image in a new tab will give you a clearer view):

My question: How can I prevent Java / Windows 8 from distorting my icons?

回答1:

The 16×16 size is apparently hardcoded into the Java TrayIcon implementation. I don't see a way to change it at runtime. From WTrayIconPeer.java:

final static int TRAY_ICON_WIDTH = 16;
final static int TRAY_ICON_HEIGHT = 16;

This needs to be reported as a bug.

As a workaround, using smooth, anti-aliased icons will make the distortion less noticeable.

If you're desperate, you could write (or find?) an alternative implementation of tray icons using JNA or JNI. The code in WTrayIconPeer.java and the corresponding native code in awt_TrayIcon.cpp could serve as a guide. It looks like a lot of work though.



回答2:

It may simply be a matter of using an icon that is a power of 2 - 16x16, 32x32, etc. Although the native OS (Windows, in your case) has support for it, java handles taskbar icons and program icons with power of 2 sized images only. Try resizing it to 32x32 and try again.