Undocumented Matlab
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT
  • SERVICES
    • Consulting
    • Development
    • Training
    • Gallery
    • Testimonials
  • PRODUCTS
    • IQML: IQFeed-Matlab connector
    • IB-Matlab: InteractiveBrokers-Matlab connector
    • EODML: EODHistoricalData-Matlab connector
    • Webinars
  • BOOKS
    • Secrets of MATLAB-Java Programming
    • Accelerating MATLAB Performance
    • MATLAB Succinctly
  • ARTICLES
  • ABOUT
    • Policies
  • CONTACT

Adding a context-menu to a uitree

March 27, 2009 35 Comments

A CSSM poster asked a few days ago whether it was possible to add a context (right-click) menu to uitree nodes. Uitree is an internal, undocumented and unsupported Matlab function, which does not enable easy setting of a uicontextmenu like its uicontrol relatives.
However, using some undocumented Java magic, it is possible to do so. Being undocumented and unsupported, this solution might break in future releases, although this is unlikely since it relies on some very basic Java functionality that is unlikely to be broken soon.
Note that the context-menu in the following example uses HTML formatting. As explained in an earlier post, all Swing components (and by extension, most Matlab uicontrols) support HTML formatting.

% Prepare the context menu (note the use of HTML labels)
menuItem1 = javax.swing.JMenuItem('action #1');
menuItem2 = javax.swing.JMenuItem('<html><b>action #2');
menuItem3 = javax.swing.JMenuItem('<html><i>action #3');
% Set the menu items' callbacks
set(menuItem1,'ActionPerformedCallback',@myFunc1);
set(menuItem2,'ActionPerformedCallback',{@myfunc2,data1,data2});
set(menuItem3,'ActionPerformedCallback','disp ''action #3...'' ');
% Add all menu items to the context menu (with internal separator)
jmenu = javax.swing.JPopupMenu;
jmenu.add(menuItem1);
jmenu.add(menuItem2);
jmenu.addSeparator;
jmenu.add(menuItem3);
% Set the tree mouse-click callback
% Note: MousePressedCallback is better than MouseClickedCallback
%       since it fires immediately when mouse button is pressed,
%       without waiting for its release, as MouseClickedCallback does
set(jtree, 'MousePressedCallback', {@mousePressedCallback,jmenu});
% Set the mouse-press callback
function mousePressedCallback(hTree, eventData, jmenu)
   if eventData.isMetaDown  % right-click is like a Meta-button
      % Get the clicked node
      clickX = eventData.getX;
      clickY = eventData.getY;
      jtree = eventData.getSource;
      treePath = jtree.getPathForLocation(clickX, clickY);
      try
         % Modify the context menu or some other element
         % based on the clicked node. Here is an example:
         node = treePath.getLastPathComponent;
         nodeName = ['Current node: ' char(node.getName)];
         item = jmenu.add(nodeName);
         % remember to call jmenu.remove(item) in item callback
         % or use the timer hack shown here to remove the item:
         timerFcn = {@removeItem,jmenu,item};
         start(timer('TimerFcn',timerFcn,'StartDelay',0.2));
      catch
         % clicked location is NOT on top of any node
         % Note: can also be tested by isempty(treePath)
      end
      % Display the (possibly-modified) context menu
      jmenu.show(jtree, clickX, clickY);
      jmenu.repaint;
   end
end
% Remove the extra context menu item after display
function removeItem(hObj,eventData,jmenu,item)
   jmenu.remove(item);
end
% Menu items callbacks must receive at least 2 args:
% hObject and eventData – user-defined args follow after these two
function myfunc1(hObject, eventData)
   % ... 
function myFunc2(hObject, eventData, myData1, myData2)
    % ... 

uitree node-specific context-menu
uitree node-specific context-menu
(note the HTML formatting of menu items)

If the issue of undocumented Matlab interests you, please review the list of future post topics and let me know if you have any preference, or would like to see some other (unlisted) topics.
Yair

Related posts:

  1. Customizing uitree nodes – part 2 – This article shows how Matlab GUI tree nodes can be customized with checkboxes and similar controls...
  2. Customizing uitree nodes – part 1 – This article describes how to customize specific nodes of Matlab GUI tree controls created using the undocumented uitree function...
  3. Adding custom properties to GUI objects – It is very easy to add custom user-defined properties and methods to GUI handles and Java references in Matlab. ...
  4. PlotEdit context-menu customization – A combination of Matlab and Java Robot commands to automate a certain animation can be used when we cannot access underlying GUI/graphics code. ...
  5. uitree – This article describes the undocumented Matlab uitree function, which displays data in a GUI tree component...
  6. Adding a search box to figure toolbar – An interactive search-box can easily be added to a Matlab figure toolbar for enhanced user experience. ...
GUI Java uicontrol
Print Print
« Previous
Next »
35 Responses
  1. Darik Gamble March 27, 2009 at 19:20 Reply

    Yair,

    I’m glad to see you’ve got a blog — I remember learning from your newsgroup posts a couple years ago that I could add custom properties and event listeners to handle graphics objects, and both features have helped me immensely (and made it into the Matlab documention!)

    My votes on your to do list include customizing menus and the two schema topics.

    Cheers,

    dg

  2. Venky March 31, 2009 at 21:27 Reply

    Yair,
    It’s interesting to know that it is possible to add uicontextmenus to uitree.
    Your post saved my time.
    Thanks a lot

  3. Scott Koch June 9, 2009 at 15:00 Reply

    If you have access to the figure handle (stored as User Data for instance) you could also use the click event coordinates to display a GUIDE created context menu:

    ...
    if eventData.isMetaDown
      fh = get(hTree,'UserData');%Get figure handle
      cm = findobj(fh,'tag','mycontextmenu');%Get context menu handle.
      tpos = get(hTree,'PixelPosition');
     
      set(cm,'position',[eventData.getX()+tpos(1) (tpos(4)-eventData.getY)+tpos(2)],'Visible','on');
     
    ...

    ... if eventData.isMetaDown fh = get(hTree,'UserData');%Get figure handle cm = findobj(fh,'tag','mycontextmenu');%Get context menu handle. tpos = get(hTree,'PixelPosition'); set(cm,'position',[eventData.getX()+tpos(1) (tpos(4)-eventData.getY)+tpos(2)],'Visible','on'); ...

  4. Setting listbox mouse actions | Undocumented Matlab September 15, 2009 at 06:30 Reply

    […] months ago I explained how to set a context (right-click) menu on a uitree control. I shall now show how to implement a similar dynamic context-menu on a listbox. The code is an […]

  5. Bass July 7, 2010 at 16:35 Reply

    Awesome article.

    I was looking for something that would allow me to create a right click context menu for any figure or uitable.

    When I use similar code (see below for example with a figure) I don’t get any context window displayed (although the mousePressedCallback is called). The same code using the handle of juitable, doesn’t even result in the mousePressCallback being called

    Am I doing something wrong or is this

    h = figure;
    juit = findjobj(h);
     
    % Prepare the context menu (note the use of HTML labels)
    menuItem1 = javax.swing.JMenuItem('action #1');
     
    % Set the menu items' callbacks
    set(menuItem1,'ActionPerformedCallback',@myFunc1);
     
    % Add all menu items to the context menu (with internal separator)
    jmenu = javax.swing.JPopupMenu;
    jmenu.add(menuItem1);
     
    set(juit, 'MousePressedCallback', {@mousePressedCallback,jmenu});
     
    function mousePressedCallback(hTree, eventData, jmenu)
       display('here')
       jmenu.repaint;
    end

    h = figure; juit = findjobj(h); % Prepare the context menu (note the use of HTML labels) menuItem1 = javax.swing.JMenuItem('action #1'); % Set the menu items' callbacks set(menuItem1,'ActionPerformedCallback',@myFunc1); % Add all menu items to the context menu (with internal separator) jmenu = javax.swing.JPopupMenu; jmenu.add(menuItem1); set(juit, 'MousePressedCallback', {@mousePressedCallback,jmenu}); function mousePressedCallback(hTree, eventData, jmenu) display('here') jmenu.repaint; end

    • Yair Altman July 7, 2010 at 16:56 Reply

      @Bassam – you forgot the all-important display of the jmenu:

      jmenu.show(jComponent, jEventData.getX, jEventData.getY)

      jmenu.show(jComponent, jEventData.getX, jEventData.getY)

      (jComponent can be real or [])

  6. Customizing uitree | Undocumented Matlab August 25, 2010 at 11:02 Reply

    […] As an example customization that uses jtree, consider one of my earliest articles on this website: Adding a context-menu to a uitree. […]

  7. Yan November 8, 2012 at 03:03 Reply

    Hi Yair,

    Good work, very useful post. I was wondering if you can also add specific Tool Tip on nodes (not for the entire tree) possibly different ones depending on node hierarchy.

    Thanks!

    • Yair Altman November 8, 2012 at 11:37 Reply

      @Yan – you could trap the relevant events using Matlab callbacks, as I have explained in http://undocumentedmatlab.com/blog/setting-listbox-mouse-actions/. You’d probably be looking for the MouseMoved event/callback. I explain the mechanism in Section 6.6.3 (page 406) of my Matlab-Java programming book.

  8. Nuno Benavente May 11, 2013 at 10:26 Reply

    Hello Yair,
    First of all, congratulations for your book and excellent blog.
    I’ve been trying to implement a context menu to my needs but I’m stuck.
    Say my uitree displays a list of text file names (e.g. image1.txt, image2.txt, …)
    I want my context menu’s first option to be something like ‘visualize matrix’ of the image I right click in…
    How do I pass that information to my 1st context menu option’s callback function?

    Thank you very much in advance!
    Nuno

    • Nuno Benavente May 12, 2013 at 08:45 Reply

      Nevermind, I figured out a solution.
      Thank you anyway 🙂

  9. Nuno Benavente May 13, 2013 at 04:58 Reply

    Well, now I have another problem and I suck at java; perhaps you can help?
    One of my mtree’s context menu options is ‘delete file’ so, in my callback, after I delete the file, I’d like my tree to be ‘refreshed’ (I’m displaying it in a GUI, with a uipanel as parent).
    My approach to create the original nodes was through a for cycle, reading all the files in a given folder and creating the nodes one by one. That works fine, but after I delete one file is there a simple way to ‘redraw’ my mtree inside the same uipanel?

    Thanks!

    • Yair Altman May 28, 2013 at 17:27 Reply

      @Nuno – you’d need to remove the relevant node and then repaint() the tree object

  10. Ioannis January 17, 2014 at 06:18 Reply

    Dear Yair,

    Is it possible by double clicking a specific node of the uitree to open a new GUI window or figure? Can you give an example?

    Thanks

  11. Chris Hoogeboom March 14, 2014 at 10:00 Reply

    Hi Yair,

    Great article! I’m trying to implement this in MATLAB R2014a, but I am unable to set the ‘MousePressedCallback’ for the uitree object. I get the following error when I try to set it on the tree object returned by uitree

    set(tree, 'MousePressedCallback', callback);
     
    Error using javahandle_withcallbacks.com.mathworks.hg.peer.UITreePeer/set
    The name 'MousePressedCallback' is not an accessible property for an instance of class
    'com.mathworks.hg.peer.UITreePeer'.

    set(tree, 'MousePressedCallback', callback); Error using javahandle_withcallbacks.com.mathworks.hg.peer.UITreePeer/set The name 'MousePressedCallback' is not an accessible property for an instance of class 'com.mathworks.hg.peer.UITreePeer'.

    The following does not work either

    set(tree.getTree(), 'MousePressedCallback', callback);
     
    Error using DependencyMap/displayReport (line 281)
    The name 'MousePressedCallback' is not an accessible property for an instance of class
    'com.mathworks.hg.peer.utils.UIMJTree'.

    set(tree.getTree(), 'MousePressedCallback', callback); Error using DependencyMap/displayReport (line 281) The name 'MousePressedCallback' is not an accessible property for an instance of class 'com.mathworks.hg.peer.utils.UIMJTree'.

    Do you know of any other way to set the MousePressedCallback, or is this undocumented feature broken now?

    • Yair Altman March 15, 2014 at 17:37 Reply
      hTree = handle(tree.getTree, 'CallbackProperties');
      set(hTree, 'MousePressedCallback', callback);

      hTree = handle(tree.getTree, 'CallbackProperties'); set(hTree, 'MousePressedCallback', callback);

  12. Ramiro Massol March 17, 2014 at 06:04 Reply

    hi Yair
    just to let you know that the new version of matlab, 2014a, has somehow removed all callbacks from JMenuItem. I found this when I tried to use create table with JMenuItems and “ActionPerformedCallback” as a callback (line 493). I’m not sure there’s any way to fix this problem,
    best
    ramiro

    • Chris Hoogeboom March 18, 2014 at 11:35 Reply

      You can used the ‘MousePressedCallback’ instead. See Yair’s response to my question above.

      • Ramiro Massol March 20, 2014 at 05:26

        hi Yair and Chris
        thanks Chris for the tip, but unfortunately the bright minds at Mathworks remove more than just the callbacks for JMenuItems but also almost everything linked to Java. I have many GUIs depending on JTextFields, JComboBoxes, etc, and none of the callbacks show up anymore.
        best

      • Yair Altman March 20, 2014 at 05:44

        @Ramiro – MathWorks only removed the ability to access callbacks on naked Java references, but you can still use the handle(javaObject,’CallbackProperties’) syntax to use them, just as before. In fact, this has always been the preferred alternative, as explained here. If you look at my answer to Chris above, this is exactly what I did.

  13. Ramiro Massol March 21, 2014 at 05:24 Reply

    thanks Yair, the handle syntax works ok now. By the way, I also noticed that the functions enableDisableFig and statusbar don’t work well with the R2014a. I fixed some issues with enableDisableFig (e.g. when using R2014 and setting the enable/edit state, it must be using 1 or 0, nor ‘on’ or ‘off’ as in the past).

  14. Ramiro Massol March 25, 2014 at 05:56 Reply

    hi Yair
    I just realized that if I use handle(javaObject,…) anytime in a JMenu, this will prevent normal function of any java controls launched after firing any of the callbacks of the Jmenu. The callbacks of the java controls are triggered but if any of those tries to call subimage, bar, plot, etc, they won’t do anything at all and no errors will show up. Any ideas on this?
    best

    • Yair Altman March 25, 2014 at 15:35 Reply

      This sounds very strange to me. I haven’t encountered a similar phenomenon before. The HG functions are supposed to be entirely independent of Java, they don’t mix at all.

      • Ramiro Massol March 26, 2014 at 04:53

        hi, I agree it’s very odd behavior. It’s easy to reproduce. If you create a GUI (let’s name it FirstGUI) with let’s say a jslider controlling the display on the same GUI of 2 images (use subimage to display them). Then create another GUI figure with a table (use createtable for this) and associate a contextmenu that will just launch the first GUI (the one with the jslider). Now, if you run FirstGUI and launch the jslider GUI using the contextmenu callback, the jslider GUI will display normally and the jslider will work fine scrolling between the 2 images. However, if you use the handle function when creating the JMenuItem of the contextmenu, the jslider callback will be fired but the image shown will not refresh.

      • Ramiro Massol March 27, 2014 at 06:57

        a guy at mathworks fixed the problem, I just needed to add:

        set(0,'ShowHiddenHandles','on')

        set(0,'ShowHiddenHandles','on')

        to allow for this bug to go away.
        best

      • Yair Altman March 27, 2014 at 07:32

        It sounds like you have updated the GUI using gcf, gca, or direct plotting (via plot or image), without directly specifying the target container handle. Since you use hidden handles in your code, the function targets whatever GUI container that has a non-hidden handle was last made active. By setting the ShowHiddenProperties of the root you simply made all handles visible, but this merely hides the root cause of your problem, which is the fact that you have not directly specified the target handle. Once you do that, there will no longer be a need for setting ShowHiddenProperties.

        In short, it’s an application bug, not a Matlab bug.

      • Ramiro Massol March 27, 2014 at 11:27

        I’m not sure it’s an application bug. Before subimage I actually target both the figure and the axes by using “figure(handle); axes(axeshandle)”. I have not used gcf or gca at all. Thanks anyway,
        best

  15. Deepak Bhatia September 4, 2015 at 08:45 Reply

    Hi,
    I am also trying to set the MousePressedCallback of jtree where jtree is com.mathworks.hg.peer.utils.UIMJTree.
    I dont know Java at all but I am modifying an exisiting code to work with ML2015. I get the error

    The name 'MousePressedCallback' is not an accessible property for an instance of class 'com.mathworks.hg.peer.utils.UIMJTree

    The name 'MousePressedCallback' is not an accessible property for an instance of class 'com.mathworks.hg.peer.utils.UIMJTree

    Any Ideas how I can do this: i noticed that the jtree.getTree is also not present.
    I just have the following.
    jtree.getTreeSelectionListeners
    Help will be appreciated

    • Yair Altman September 5, 2015 at 10:27 Reply

      http://undocumentedmatlab.com/blog/matlab-callbacks-for-java-events-in-r2014a

  16. Ian Alan February 6, 2018 at 06:29 Reply

    Yair,

    I am trying to create a uitree one a resizable panel created with your uisplitpane() function.

    The tree won’t show up at all in the figure until I drag the divider around with the mouse to resize the panes, and then it shows up like it should. Do you have any suggestions on how I could fix this?

    I am using MATLAB 2011a, if it matters.

    • Yair Altman February 6, 2018 at 11:20 Reply

      @Ian – try to call the Java object’s repaint() method (function), after adding it to the panel (presumably using a call to javacomponent)

  17. Hironori Tokuno September 6, 2018 at 09:33 Reply

    Hello Mr. Altman

    Thank you for this variable informations

    How could I get the Output variable from the function “myFunc2” using the command
    “set(menuItem2,'ActionPerformedCallback',{@myFunc2,data1,data2});” at this case?

    % -- Example
    function output = myFunc2(hObject, eventData, myData1, myData2)
    output = myData1 + myData2;
    end

    % -- Example function output = myFunc2(hObject, eventData, myData1, myData2) output = myData1 + myData2; end

    I need to get the variable “output” into my main function after the mouse right button action was performed.

    Will you please advise me for this?

    Thanks in advance
    Best regards
    Hiro Tokuno

    • Yair Altman September 6, 2018 at 10:09 Reply

      @Hironori – callback functions run asynchronously, not synchronously, so they do not return any value. You can save the results in some persistent place (like a global variable or the figure’s UserData property) and in your main program you can later access this data. You can read about Matlab callbacks and how to use them in Matlab’s standard documentation.

  18. Yerlan January 15, 2021 at 17:41 Reply

    Hello Mr. Altman,

    how can I disable menu items in the context menu?

    E.g. when I am trying to do this:

    menuItems = jmenu.getSubElements;
    menuItem1 = menuItems(1); 
    set(menuItem1,'setEnabled',0);

    menuItems = jmenu.getSubElements; menuItem1 = menuItems(1); set(menuItem1,'setEnabled',0);

    I get an error: “The name ‘setEnabled’ is not an accessible property for an instance of class ‘javax.swing.JMenuItem’.”

    Thank you.

    Best regards,
    Yerlan

    • Yair Altman January 17, 2021 at 01:20 Reply

      Yerlan – either use menuItem1.setEnabled(0) or set(menuItem1,'Enabled',0)

Leave a Reply
HTML tags such as <b> or <i> are accepted.
Wrap code fragments inside <pre lang="matlab"> tags, like this:
<pre lang="matlab">
a = magic(3);
disp(sum(a))
</pre>
I reserve the right to edit/delete comments (read the site policies).
Not all comments will be answered. You can always email me (altmany at gmail) for private consulting.

Click here to cancel reply.

Useful links
  •  Email Yair Altman
  •  Subscribe to new posts (feed)
  •  Subscribe to new posts (reader)
  •  Subscribe to comments (feed)
 
Accelerating MATLAB Performance book
Recent Posts

Speeding-up builtin Matlab functions – part 3

Improving graphics interactivity

Interesting Matlab puzzle – analysis

Interesting Matlab puzzle

Undocumented plot marker types

Matlab toolstrip – part 9 (popup figures)

Matlab toolstrip – part 8 (galleries)

Matlab toolstrip – part 7 (selection controls)

Matlab toolstrip – part 6 (complex controls)

Matlab toolstrip – part 5 (icons)

Matlab toolstrip – part 4 (control customization)

Reverting axes controls in figure toolbar

Matlab toolstrip – part 3 (basic customization)

Matlab toolstrip – part 2 (ToolGroup App)

Matlab toolstrip – part 1

Categories
  • Desktop (45)
  • Figure window (59)
  • Guest bloggers (65)
  • GUI (165)
  • Handle graphics (84)
  • Hidden property (42)
  • Icons (15)
  • Java (174)
  • Listeners (22)
  • Memory (16)
  • Mex (13)
  • Presumed future risk (394)
    • High risk of breaking in future versions (100)
    • Low risk of breaking in future versions (160)
    • Medium risk of breaking in future versions (136)
  • Public presentation (6)
  • Semi-documented feature (10)
  • Semi-documented function (35)
  • Stock Matlab function (140)
  • Toolbox (10)
  • UI controls (52)
  • Uncategorized (13)
  • Undocumented feature (217)
  • Undocumented function (37)
Tags
AppDesigner (9) Callbacks (31) Compiler (10) Desktop (38) Donn Shull (10) Editor (8) Figure (19) FindJObj (27) GUI (141) GUIDE (8) Handle graphics (78) HG2 (34) Hidden property (51) HTML (26) Icons (9) Internal component (39) Java (178) JavaFrame (20) JIDE (19) JMI (8) Listener (17) Malcolm Lidierth (8) MCOS (11) Memory (13) Menubar (9) Mex (14) Optical illusion (11) Performance (78) Profiler (9) Pure Matlab (187) schema (7) schema.class (8) schema.prop (18) Semi-documented feature (6) Semi-documented function (33) Toolbar (14) Toolstrip (13) uicontrol (37) uifigure (8) UIInspect (12) uitable (6) uitools (20) Undocumented feature (187) Undocumented function (37) Undocumented property (20)
Recent Comments
Contact us
Captcha image for Custom Contact Forms plugin. You must type the numbers shown in the image
Undocumented Matlab © 2009 - Yair Altman
This website and Octahedron Ltd. are not affiliated with The MathWorks Inc.; MATLAB® is a registered trademark of The MathWorks Inc.
Scroll to top