Customizing menu items part 3

In the past weeks I’ve shown how Matlab menus can be customized in a variety of undocumented manners, using HTML, pure Matlab, and Java. Today I conclude this mini-series with an article that explains how to use the underlying Java object to customize menu item icons. Menu customizations are explored in depth in section 4.6 of my book.

A reminder: accessing the underlying Java object

Matlab menus (uimenu) are basically simple wrappers for the much more powerful and flexible Java Swing JMenu and JMenuItem on which they are based. Many important functionalities that are available in Java menus are missing from the Matlab uimenus.

Getting the Java reference for the figure window’s main menu is very easy:

jFrame = get(handle(hFig),'JavaFrame');
try
    % R2008a and later
    jMenuBar = jFrame.fHG1Client.getMenuBar;
catch
    % R2007b and earlier
    jMenuBar = jFrame.fFigureClient.getMenuBar;
end

There are many customizations that can only be done using the Java handle: setting icons, several dozen callback types, tooltips, background color, font, text alignment, and so on. etc. Interested readers may wish to get/set/inspect/methodsview/uiinspect the jSave reference handle and/or to read the documentation for JMenuItem. Today’s article will focus on icon customizations.

Setting simple menu item icons

Many of Matlab’s icons reside in either the [matlabroot '/toolbox/matlab/icons/'] folder or the [matlabroot '/java/jar/mwt.jar'] file (a JAR file is simply a zip file that includes Java classes and resources such as icon images). Let us create icons from the latter, to keep a consistent look-and-feel with the rest of Matlab (we could just as easily use our own external icon files):

% External icon file example
jSave.setIcon(javax.swing.ImageIcon('C:\Yair\save.gif'));
 
% JAR resource example
jarFile = fullfile(matlabroot,'/java/jar/mwt.jar');
iconsFolder = '/com/mathworks/mwt/resources/';
iconURI = ['jar:file:/' jarFile '!' iconsFolder 'save.gif'];
iconURI = java.net.URL(iconURI);  % not necessary for external files
jSave.setIcon(javax.swing.ImageIcon(iconURI));

Note that setting a menu item’s icon automatically re-aligns all other items in the menu, including those that do not have an icon (an internal bug that was introduced in R2010a causes a misalignment, as shown below):

Menu item with a custom Icon (R2009b)

Menu item with a custom Icon (R2009b)

   
...and the same in R2010a onward

...and the same in R2010a onward

Checkmark icon

The empty space on the left of the menu is reserved for the check mark. Each Matlab menu item is check-able, since it is an object that extends the com.mathworks.mwswing.MJCheckBoxMenuItem class. I have not found a way to eliminate this empty space, which is really unnecessary in the File-menu case (it is only actually necessary in the View and Tools menus). Note that if an icon is set for the item, both the icon and the checkmark will be displayed, side by side.

The check mark is controlled by the State property of the Java object (which accepts logical true/false values), or the Checked property of the Matlab handle (which accepts the regular ‘on’/'off’ string values):

% Set the check mark at the Matlab level
set(findall(hFig,'tag','figMenuFileSave'), 'Checked','on');
 
% Equivalent - set the checkmark at the Java level
jSave.setState(true);

State = true, Icon = [ ]

State = true, Icon = [ ]

   
State = true, Icon = custom

State = true, Icon = custom

Customizing menu icons

Icons can be customized: modify the gap between the icon and the label with the IconTextGap property (default = 4 [pixels]); place icons to the right of the label by setting HorizontalTextPosition to jSave.LEFT (=2), or centered using jSave.CENTER (=0). Note that the above-mentioned misalignment bug does not appear in these cases:

jSave.setHorizontalTextPosition(jSave.LEFT)

jSave.setHorizontalTextPosition
(jSave.LEFT)

   
jSave.setHorizontalTextPosition(jSave.CENTER)

jSave.setHorizontalTextPosition
(jSave.CENTER)

Note how the label text can be seen through (or on top of) the icon when it is centered. This feature can be used to create stunning menu effects as shown below. Note how the width and height of the menu item automatically increased to accommodate my new 77×31 icon size (icons are normally sized 16×16 pixels):

Overlaid icon (HorizontalTextPosition = CENTER)

Overlaid icon (HorizontalTextPosition = CENTER)

To resize an icon programmatically before setting it in a Java component, we can use the following example:

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

Remember when rescaling images, particularly small ones with few pixels, that it is always better to shrink than to enlarge images: enlarging a small icon image might introduce a significant pixelization effect:

16x16 icon image resized to 32x32

16x16 icon image resized to 32x32

Separate icons can be specified for a different appearance during mouse hover (RolloverIcon; requires RolloverEnabled=1), item click/press (PressedIcon), item selection (SelectedIcon, RolloverSelectedIcon, DisabledSelectedIcon), and disabled menu item (DisabledIcon). All these properties are empty ([]) by default, which applies a predefined default variation (image color filter) to the main item’s Icon. For example, let us modify DisabledIcon:

myIcon = 'C:\Yair\Undocumented Matlab\Images\save_disabled.gif';
jSaveAs.setDisabledIcon(javax.swing.ImageIcon(myIcon));
jSaveAs.setEnabled(false);

Enabled, main Icon

Enabled, main Icon

   
Disabled, default Icon variation

Disabled, default Icon variation

   
Disabled, custom DisabledIcon

Disabled, custom DisabledIcon

Note the automatic graying of disabled menu items, including their icon. This effect can also be achieved programmatically using the static methods in com.mathworks.mwswing.IconUtils: changeIconColor(), createBadgedIcon(), createGhostedIcon(), and createSelectedIcon(). When we use a non-default custom DisabledIcon, it is used instead of the gray icon variant.

This concludes my mini-series of customizing menus in Matlab. If you have used any nifty customization that I have not mentioned, please post a comment about it below.

Ken & MikeIn an unrelated note, I would like to extend good wishes to Mike Katz, who has left the MathWorks mobile development team to join Kinvey a few days ago. Mike has been with MathWorks since 2005 and has been responsible for maintaining the official MATLAB Desktop blog, together with Ken Orr. I’m not sure yet which direction the Desktop blog will take, and by whom, but in any case it won’t be the same. You’re both missed, Mike & Ken!

 

Related posts:

  1. Customizing menu items part 2 Matlab menu items can be customized in a variety of useful ways using their underlying Java object. ...
  2. Customizing menu items part 1 Matlab menus can be customized in a variety of undocumented manners - first article of a series. ...
  3. Customizing uitree nodes – part 1 This article describes how to customize specific nodes of Matlab GUI tree controls created using the undocumented uitree function...
  4. Customizing uitree nodes – part 2 This article shows how Matlab GUI tree nodes can be customized with checkboxes and similar controls...
  5. Customizing Workspace context-menu Matlab's Workspace table context-menu can be configured with user-defined actions - this article explains how....
  6. Disabling menu entries in deployed docked figures Matlab's standard menu items can and should be removed from deployed docked figures. This article explains how. ...

Categories: GUI, Icons, Java, Medium risk of breaking in future versions, Undocumented feature

Tags: , , , , ,

Bookmark and Share Print Print

18 Responses to Customizing menu items part 3

  1. John says:

    Yair, is there any way to have the menu remain open after clicking it? Suppose you wanted to have a menu with a bunch of booleans, and you wanted to be able to quickly change the state of a bunch of them without doing click, reopen, click, reopen….

    Thanks,
    John

  2. Morteza says:

    Hi
    You have nice web site and it is very interisting (Thanks)
    I tried to insert an icon in Save file menu according to your doc.

    figure(1)
    jFrame    = get(handle(gcf),'JavaFrame')
    jMenuBar  = jFrame.fHG1Client.getMenuBar;
    jFileMenu = jMenuBar.getComponent(0)
    jMER      = jFileMenu.getMenuComponent(1)
    jMER.setIcon(javax.swing.ImageIcon(im2java(A)));

    But when MATLAB
    reach to below line of my command line :
    jMER = jFileMenu.getMenuComponent(1)
    it set a message that it is:

    Error using com.mathworks.hg.peer.MenuPeer$FigureMJMenu/getMenuComponent
    Java exception occurred:
    java.lang.ArrayIndexOutOfBoundsException: No such child: 1
    	at java.awt.Container.getComponent(Unknown Source)
    	at javax.swing.JMenu.getMenuComponent(Unknown Source)

    Can you help me please?

  3. Morteza says:

    Hi Dear Yair
    I try to put the icons for uicontextmenu in my program but I couldn’t. Can you help me.

    B.cm = uicontextmenu;
    B.um(1) = uimenu(B.cm,'label','Statistical val.',...
                    'Callback', {@BM1_call,B},'foregroundcolor',[0.2863 0.0667 0.0157]);   
    B.um(2) = uimenu(B.cm,'label','Plot ...','Separator','on',...
                    'Callback', {@BM2_call,B},'foregroundcolor',[0.2863 0.0667 0.0157]);

    Thanks.

    • Yair Altman says:

      @Morteza – You could try to use HTML images, as explained here. But perhaps a better way is to use Java icons in a Java context-menu, rather than a Matlab uicontextmenu.

      If you have additional programming requests, please contact me by email for personal consulting.

    • Morteza says:

      Hi dear Yair
      I try to put an image in uicontextmenu by html functions.
      I use the : src=”" (function that shows image)

      txtimg = '<html><img src="myimage.png"/><font size="3">Color-Map</font></html>'; 
      uimenu(F.cm,'label',txtimg,'Callback',{@FM1_call,F});

      Even I put the root directory path like :
      but nothing happened and just cross sign is shown.
      but when I execute my GUI, MATLAB does not show the image in uicontextmenu.
      Can you help me?

    • Yair Altman says:

      @Morteza – this will be answered in my next article, so stay tuned…

    • Morteza says:

      Hi Dear Yair
      I’ll follow your articles…
      Thanks anyway

  4. Morteza says:

    Hi Dear Yair
    last part I asked about put the image using of html format.
    I use the pwd function in MATLAB and I found there is diffrent root path between Windows and html.
    in windows pwd : C:\Program Files\MATLAB\R2012a\bin
    but in html format : http://undocumentedmatlab.com/blog/customizing-menu-items-part-3/
    ‘/’ insted of ‘\’.
    but when I try to do this in MATLAB but nothing appear!!!
    Is there something that I should use extra?
    Thank you so much

  5. Morteza says:

    Hi Dear Yair
    I try to open link of your E-mail from your web-site but I couldn’t.
    So,I have a question about subject that I know it is not related to this page article, then excuse me.
    Is it possible to write a program after make it as stand-alone application (*.exe) by compiler’s MATLAB ,at specific time delete itself to prevent extra use?
    Thanks

  6. Shuhao Cao says:

    Hi, Yair
    Your website is so helpful! I followed some of the matlab customization on your website, now I wonder if I could change the font used in the MATLAB, like I tried something like:

    com.mathworks.services.Prefs.setFontPref('MenuFont',java.awt.Font('Ubuntu',0,13))

    but nothing happened.
    Thanks.

    • Yair Altman says:

      @Shuhao – after modifying the prefs you need to restart Matlab. You need to ensure (of course) that the relevant preference name exists.

    • Shuhao Cao says:

      Thanks for the quick reply. Is there a way to see what are all the relevant preference names?

    • Yair Altman says:

      Of course – simply open the preferences file in a text editor

      edit([prefdir '/matlab.prf'])
    • Shuhao Cao says:

      Haha, I see. Thanks a lot. I have looked into it but found no ‘MenuFont’. Guess there is no easy workaround within MATLAB to change the font size of the menu then.

Leave a Reply

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

*

<pre lang="matlab">
a = magic(3);
sum(a)
</pre>