Matlab listbox uicontrols enable basic mouse support, by exposing the ButtonDownFcn callback property. When set, this callback is activated whenever a mouse button (left or right-click) is pressed within the listbox confines. Often this is enough, but in some cases not: since right-clicks do not modify the selected listbox item, we can trap right-click events, but we cannot know which item was clicked-on, as recently noted on the CSSM forum.
Another limitation of the basic Matlab listbox is that it only enables simple static TooltipString and UIContextMenu properties – it would be much more useful to have dynamic tooltips and context-menus based on the item on which the mouse actually hovers.
Processing mouse right-clicks
These limitations, and many others, can be overcome using the underlying Java component of the Matlab uicontrol. We can get this Java component using my FindJObj utility on the Matlab File Exchange. We can then use the many exposed Java component callback hooks to trap our desired mouse-click or mouse-movement event.
Let’s start with a simple Matlab-code callback code that displays the clicked item and the mouse-click type:
% Prepare the Matlab listbox uicontrol hFig = figure; listItems = {'apple','orange','banana','lemon','cherry','pear','melon'}; hListbox = uicontrol(hFig, 'style','listbox', 'pos',[20,20,60,60], 'string',listItems); % Get the listbox's underlying Java control jScrollPane = findjobj(hListbox); % We got the scrollpane container - get its actual contained listbox control jListbox = jScrollPane.getViewport.getComponent(0); % Convert to a callback-able reference handle jListbox = handle(jListbox, 'CallbackProperties'); % Set the 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(jListbox, 'MousePressedCallback',{@myCallbackFcn,hListbox}); % Define the mouse-click callback function function myCallbackFcn(jListbox,jEventData,hListbox) % Determine the click type % (can similarly test for CTRL/ALT/SHIFT-click) if jEventData.isMetaDown % right-click is like a Meta-button clickType = 'Right-click'; else clickType = 'Left-click'; end % Determine the current listbox index % Remember: Java index starts at 0, Matlab at 1 mousePos = java.awt.Point(jEventData.getX, jEventData.getY); clickedIndex = jListbox.locationToIndex(mousePos) + 1; listValues = get(hListbox,'string'); clickedValue = listValues{clickedIndex}; fprintf('%s on item #%d (%s)\n', clickType, clickedIndex, clickedValue); end % mousePressedCallback
Setting dynamic right-click context menu
Some 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 extension of the segment resented above:
% 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 mouse-click event 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(jListbox, 'MousePressedCallback', {@mousePressedCallback,hListbox,jmenu}); % Mouse-click callback function mousePressedCallback(jListbox, jEventData, hListbox, jmenu) if jEventData.isMetaDown % right-click is like a Meta-button % Get the clicked list-item %jListbox = jEventData.getSource; mousePos = java.awt.Point(jEventData.getX, jEventData.getY); clickedIndex = jListbox.locationToIndex(mousePos) + 1; listValues = get(hListbox,'string'); clickedValue = listValues{clickedIndex}; % Modify the context menu or some other element % based on the clicked item. Here is an example: item = jmenu.add(['<html><b><font color="red">' clickedValue]); % 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)); % Display the (possibly-modified) context menu jmenu.show(jListbox, jEventData.getX, jEventData.getY); jmenu.repaint; else % Left-click - do nothing (do NOT display context-menu) end end % mousePressedCallback % 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) % ...

Listbox dynamic context (right-click) menu
Setting dynamic tooltips (trapping mouse movements)
As a final example for today, let’s set a dynamic tooltip message, based on the actual mouse hover position. For this we need to trap the MouseMovedCallback property of the Java control:
% Set the mouse-movement event callback set(jListbox, 'MouseMovedCallback', {@mouseMovedCallback,hListbox}); % Mouse-movement callback function mouseMovedCallback(jListbox, jEventData, hListbox) % Get the currently-hovered list-item mousePos = java.awt.Point(jEventData.getX, jEventData.getY); hoverIndex = jListbox.locationToIndex(mousePos) + 1; listValues = get(hListbox,'string'); hoverValue = listValues{hoverIndex}; % Modify the tooltip based on the hovered item msgStr = sprintf('<html>item #%d: <b>%s</b></html>', hoverIndex, hoverValue); set(hListbox, 'Tooltip',msgStr); end % mouseMovedCallback

Listbox dynamic tooltip
Related posts:
- Customizing listbox & editbox scrollbars Matlab listbox and multi-line editbox uicontrols have pre-configured scrollbars. This article shows how they can be customized....
- Adding a context-menu to a uitree uitree is an undocumented Matlab function, which does not easily enable setting a context-menu. Here's how to do it....
- Setting line position in an edit-box uicontrol Matlab uicontrols have many useful features that are only available via Java. Here's how to access them....
- Setting status-bar text The Matlab desktop and figure windows have a usable statusbar which can only be set using undocumented methods. This post shows how to set the status-bar text....
- Setting system tray icons System-tray icons can be programmatically set and controlled from within Matlab, using new functionality available since R2007b....
- Setting status-bar components Matlab status-bars are Java containers in which we can add GUI controls such as progress-bars, not just simple text labels...
Tags: callbacks, FindJObj, GUI, Java, uicontrol
Categories: GUI, Java, Medium risk of breaking in future versions, UI controls
This entry was posted
on Thursday, August 13th, 2009 at 3:31 pm PST
You can follow any responses to this entry through the RSS 2.0 feed.
You can leave a response, or trackback from your own site.

Hi!!
I tried the above code; In order to make it work, you need to change eventdata into jEventdata in the code described in “Setting dynamic right-click context menu”
The first 2 lines should be:
instead of
otherwise the third line:
may return an error:
??? The class “eventData” is undefined.
Perhaps Java is not running.
Thanks for this blog, very helpful!!
Aurélien
oups I forgot to make the change in my previous comment : eventdata into jEventdata
The first 2 lines should be :
Thanks Aurélien – I fixed the post accordingly