19

I'm trying to have an icon be added and displayed to the system tray using Java. However the icon is always either too small, or its cut off in areas. Its the second one from left in case you couldn't tell.

What am I doing wrong here? How can I get this icon to be displayed fully? What's the standard icon size to be used for system tray?

Edit: I am using AWT SystemTray and TrayIcon

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Ali
  • 261,656
  • 265
  • 575
  • 769

4 Answers4

31

After you've retrieved the actual image resource from disk, you can resize it to the size you need by creating a "fake" one on-the-fly and taking its width.

I found that this was better than using the setImageAutoSize(true) method, as that method does not scale the image smoothly at all.

BufferedImage trayIconImage = ImageIO.read(getClass().getResource("/path/to/icon.png"));
int trayIconWidth = new TrayIcon(trayIconImage).getSize().width;
TrayIcon trayIcon = new TrayIcon(trayIconImage.getScaledInstance(trayIconWidth, -1, Image.SCALE_SMOOTH));
Redandwhite
  • 2,529
  • 4
  • 25
  • 43
9

To display the icon at an optimal size, you will need to manually resize it to the correct size. This correct size can differ between operating systems and preferences, so Java provides a method to acquire the task bar icon dimensions, which are 16x16 in the case of your example image.

if (SystemTray.isSupported()) {
    SystemTray tray = SystemTray.getSystemTray();
    Dimension trayIconSize = tray.getTrayIconSize();
    // resize icon image to trayIconSize
    // create your tray icon off of the resized image
}
FThompson
  • 28,352
  • 13
  • 60
  • 93
  • Resizing an image is quite simple; [here's a nice tutorial](http://www.mkyong.com/java/how-to-resize-an-image-in-java/) on it. – FThompson Sep 05 '12 at 18:04
  • 1
    16x16 looks way too small on my taskbar – Ali Sep 05 '12 at 18:07
  • According to the image in your question, 16x16 is the tray icon size for your operating system.. What does SystemTray#getTrayIconSize() return to be your tray icon size? – FThompson Sep 05 '12 at 18:09
  • what if the image file is gif? Would it be broken for a real? @Ali – gumuruh Apr 10 '22 at 07:13
9

According to TrayIcon.setImageAutoSize(boolean).

Sets the auto-size property. Auto-size determines whether the tray image is automatically sized to fit the space allocated for the image on the tray. By default, the auto-size property is set to false.

If auto-size is false, and the image size doesn't match the tray icon space, the image is painted as-is inside that space — if larger than the allocated space, it will be cropped.

Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • 5
    +1 … while the *easiest* solution would be to set the tray icon to automatically size itself, it is unfortunate that, internally, it seems to be using an unsmooth algorithm which most people will find unacceptable for production use. The auto-resized image will be unsmooth and have jagged edges. I suspect this is done for performance reasons. I normally do the resizing manually: http://stackoverflow.com/a/12287388/216104 – Redandwhite Sep 05 '12 at 18:22
  • 1
    Upvoting because, for Windows, I've defaulted this value to `true` which fixes scaling on HiDPI. Unfortunately, the icon size is improperly reported as `16x16` on Windows HiDPI, so next, I had to detect the screen scaling and apply a multiplier to the icon dimensions, then choose the right icon size. – tresf Jul 30 '19 at 21:16
2

I've ended up combining some of these answers to make the code I'm using.

This is producing a good looking icon in my system tray from a png that starts at 100x100.

It's worth noting that on a retina MacBook the icon looks worse scaled down. So I do a check elsewhere to see if it's running on a mac and don't apply this if it is.

public Image imageForTray(SystemTray theTray){

    Image trayImage = Toolkit.getDefaultToolkit().getImage("my100x100icon.png");
    Dimension trayIconSize = theTray.getTrayIconSize();
    trayImage = trayImage.getScaledInstance(trayIconSize.width, trayIconSize.height, Image.SCALE_SMOOTH);

    return trayImage;
}
Mark Bridges
  • 8,228
  • 4
  • 50
  • 65
  • 1
    This might be slightly off-topic, but I recommend using a base icon sized by a multiple of 2 (128x128 has proven to work well). Often, icon sizes are based on multiples of 2, and this will allow the image to be processed by integer-based scaling. This usually looks much better than fractional scaling (unless you have very large images). Another good choice is 96x96 pixels which has many "useful" divisors. – mzuther Jul 21 '20 at 18:32