Setting system tray icons

Java 1.6, included in Matlab releases since Matlab 7.5 (R2007b), enables programmatic access to system tray icons on such systems that support this functionality (Windows, Linux and possibly others).  If the SystemTray object indicates that it isSupported(), then a TrayIcon can be added, along with an associated tooltip and popup menu:

sysTray = java.awt.SystemTray.getSystemTray;
if (sysTray.isSupported)
   myIcon = fullfile(matlabroot,'/toolbox/matlab/icons/matlabicon.gif');
   iconImage = java.awt.Toolkit.getDefaultToolkit.createImage(myIcon);
   trayIcon = java.awt.TrayIcon(iconImage, 'initial tooltip');
   trayIcon.setToolTip('click this icon for applicative context menu');
end

sample system tray icon

sample system tray icon

The icon image can be made to automatically resize to the system-tray dimensions, using the trayIcon.setImageAutoSize(true) method (by default the icon image will maintain its original size, getting cropped or appearing small as the case may be).

Of course, after initial setup, all the sys-tray icon’s properties (icon image, popup, tooltip etc.) can be modified with convenient set methods (setImage(), setPopupMenu(), setTooltip()) or via Matlab’s set() function.

Icon popup menus are very similar in concept to Matlab uicontextmenus. Unfortunately, they need to be programmed separately since Java does not accept uicontextmenu handles. This is actually quite easy, as the following code snippet shows:

% Prepare the context menu
menuItem1 = java.awt.MenuItem('action #1');
menuItem2 = java.awt.MenuItem('action #2');
menuItem3 = java.awt.MenuItem('action #3');

% Set the menu items' callbacks
set(menuItem1,'ActionPerformedCallback',@myFunc1);
set(menuItem2,'ActionPerformedCallback',{@myfunc2,data1,data2});
set(menuItem3,'ActionPerformedCallback','disp(''action #3...'')');

% Disable one of the menu items
menuItem2.setEnabled(0);        % or: set(menuItem2,'Enabled','off');

% Add all menu items to the context menu (with internal separator)
jmenu = java.awt.PopupMenu;
jmenu.add(menuItem1);
jmenu.add(menuItem2);
jmenu.addSeparator;
jmenu.add(menuItem3);

% Finally, attach the context menu to the icon
trayIcon.setPopupMenu(jmenu);    % or: set(trayIcon,'PopupMenu',jmenu);

Tray icon context (right-click) menu

Tray icon context (right-click) menu

Unfortunately, neither the icon tooltip nor its popup menu supports HTML. The reason is that SystemTray is actually not part of Swing at all. The system-tray functionality resides in the java.awt package, and does not inherit javax.swing.JLabel’s (and Matlab uicontrols) support for HTML.

I have created a utility function called SYSTRAY, which is a convenience function that facilitates the setup and update of system tray icons. SYSTRAY (with source code) can be downloaded from the File Exchange.

In a separate post, I shall detail how informational pop-up messages can be attached to system-tray icons. This requires a bit of Java-hacking, so is beyond the scope of a single blog post.

Please note the new TODO page, which details my future posts. I would be happy to hear your requests for new topics, or telling me which topics you’d like to see earlier than others.

Addendum (May 15, 2009): A kind reader today left a comment on another post of this blog with a solution for some reported Java exceptions when using systray in Matlab R2008b onward.

Categories: Desktop, GUI, Icons, Java, Low risk of breaking in future versions

Tags: , ,

Bookmark and SharePrint Print

15 Responses to Setting system tray icons

  1. Donn Shull says:

    Hi Yair,

    I see in your TODO list that you are planning to cover the schema package. Even though the schema package is undocumented in general there are a lot of examples available in the toolbox directory to give a general sense of how to use it. There is not however a good example of how easy it is to use the schema.class javaInterfaces property to seemlessly access UDD objects from java code. I think people would be interested in that.

    Donn

  2. wei says:

    Hi Yair,
    How does one set icon image, e.g. JButton, for uicomponent you posted?

    Thank you.

    • @wei – assuming your component has a reference handle (let’s say jButton), follow this example:

      myIcon = fullfile(matlabroot,'/toolbox/matlab/icons/matlabicon.gif');
      iconImage = java.awt.Toolkit.getDefaultToolkit.createImage(myIcon);
      jButton.setIcon(javax.swing.ImageIcon(iconImage));
      

      Swing button icon

    • wei says:

      @Yair,
      I bypassed awt and directly went

       iconImage = javax.swing.ImageIcon(myIcon);
       jButton.setIcon(iconImage);
      

      Any difference?

    • @wei – your method is ok for simple filenames – I simply forgot that the ImageIcon constructor also accepts a filename. In practice, within that constructor it calls the awt Toolkit to process the file so there’s no performance difference, but obviously the code is more readable/maintainable this way. BTW, you can also use URL images, for example:

      jarFile = fullfile(matlabroot,'/java/jar/mwt.jar');
      iconsFolder = '/com/mathworks/mwt/resources/';
      myIcon = ['jar:file:/' jarFile '!' iconsFolder 'save.gif'];
      myIcon = java.net.URL(myIcon);  % not necessary for simple external files
      jSave.setIcon(javax.swing.ImageIcon(myIcon));
      

      If you wish to use the icon to set a specific component mouse cursor (hover pointer), you DO need to use the awt.Toolkit:

      myIcon = fullfile(matlabroot,'/toolbox/matlab/icons/matlabicon.gif');
      imageToolkit = java.awt.Toolkit.getDefaultToolkit;
      iconImage = imageToolkit.createImage(myIcon);
      hotSpot = java.awt.Point(20,0);   % =Matlab icon point (top) after 16x16=>32x32 resize
      myCursor = imageToolkit.createCustomCursor(iconImage,hotSpot,'My Cursor');
      jButton.setCursor(myCursor);
      

      custom button cursor

    • wei says:

      @Yair, That’s nice to know. Thank you.

  3. wei says:

    @Yair, Can one change figure’s icon wihtout JavaFrame?

    • Yair Altman says:

      wei – you can change the figure icon (not without the JavaFrame), but I’m told this may violate Matlab’s license. I’m really not sure why MathWorks (TMW) chose to limit this pretty harmless customization, but there you have it. In all my posts I try to stay on the good side of the line, so I’m afraid I can’t help you here… If you have a specific need for a customer project, then perhaps if you approach TMW they’ll agree to give you special permission.

  4. Jack Rayman says:

    Hi.

    I’m using your code like this in Matlab r2014a in windows 8.1 First I got a java exception so I used this:

    t=java.awt.Toolkit.getDefaultToolkit();
    ev=t.getAWTEventListeners()
    for i=1:length(ev)
        str=ev(i).getListener().getClass.toString
        if str.indexOf('com.mathworks.mwswing.desk.DTSelectionManager')>=0 || ...
                str.indexOf('javax.swing.plaf.basic.BasicLookAndFeel')>=0
            t.removeAWTEventListener(ev(i))
        end
    end
     
    sysTray = java.awt.SystemTray.getSystemTray;
    if (sysTray.isSupported)
        myIcon = fullfile(matlabroot,'/toolbox/matlab/icons/matlabicon.gif');
        iconImage = java.awt.Toolkit.getDefaultToolkit.createImage(myIcon);
        trayIcon = java.awt.TrayIcon(iconImage, 'initial tooltip');
        trayIcon.setToolTip('click this icon for applicative context menu');
    end

    After running this code I have a blank icon near clock without no message and without no icon. What should I do?

  5. Ange Laure says:

    Hi Yair,

    did you already get a way to fix the java exceptions in matlab?

    Thanks,
    Ange Laure

  6. Ange Laure says:

    Hi Yair,

    thanks! I get another problem. I have implemented a GUI in Java which contains Icon (ImageIcon). Then I exported the class files in a .jar file which I add to the classpath von Matlab. Unfortunately everything on the GUI appear apart from the icons. Do you know what I am doing wrong?

    Regards,
    Ange Laure

    • Matlab is obviously not finding your icon in the stated classpath…
      If you need assistance debugging your specific program, contact me by email for a short consultancy.

  7. Hi Yair,

    You recommend calling systray = java.awt.SystemTray.getSystemTray, and then systray.isSupported afterwards to check if the system tray is supported. Unfortunately, if the system tray isn’t supported (for example, I just tried this when running MATLAB remotely over an X Window), the original call to getSystemTray can error.

    Instead, you can call java.awt.SystemTray.isSupported. This returns true or false, and doesn’t error in an unsupported environment. Call getSystemTray only if that returns true.

Leave a Reply

Your email address will not be published. Required fields are marked *