Once again I’d like to welcome guest blogger Matthew Whitaker. Today Matt will discuss uicontrol tooltips hacks as the first of several posts that follow a logical thread culminating in the long promised article on the EDT.
A while back Yair wrote a cool article, Spicing up Matlab uicontrol tooltips, describing use of HTML formatting and images in uicontrol tooltips. I want to share some limitations I’ve seen with tooltips and their solution using the Matlab control’s underlying Java object.
Situation 1: Displaying a tooltip on disabled controls
One issue with the stock Matlab uicontrol tooltips is that if you turn the uicontrol’s Enable property to ‘inactive’ or ‘off’, its tooltip no longer displays. This is the behavior that we normally want, but occasionally we wish to display a tooltip on a disabled control, for example, to explain why the control is disabled.
You can use the findjobj utility to find the Java handle for the uicontrol. This handle can then be used to set the tooltip text. The tooltip will display if you disable the control using its Java handle’s Enabled property rather than the Matlab handle’s Enable property:
hButton = uicontrol('String','Button'); drawnow; jButton= findjobj(hButton); set(jButton,'Enabled',false); set(jButton,'ToolTipText','This is disabled for a reason');
As customary for Java objects, its properties can also be set using their corresponding accessor methods:
javaMethodEDT('setEnabled',jButton,false); javaMethodEDT('setToolTipText',jButton,'Button is disabled for a reason');
Unfortunately, this hack does not work for ‘inactive’ controls. There is no direct Java analogy for inactive controls – it’s a Matlab extension. It appears that Matlab somehow intercepts the mouse events associated with inactive controls. My next post will show how event callback can be used to display tooltips for inactive controls.
As an alternative for inactive edit-box controls, we can simulate the inactive behavior by setting the Java object’s Editable property (or by using its setEditable() accessor method), then setting the tooltip. Note that the extremely-useful Java Editable property is unavailable in the Matlab handle, for some inexplicable reason:
hEditbox = uicontrol('String','Edit Text','Style','edit'); drawnow; jEditbox = findjobj(hEditbox); set(jEditbox,'Editable',false); set(jEditbox,'ToolTipText','Text is inactive for a reason');
Situation 2: Displaying a tooltip on truncated text
If we want to conditionally display a tooltip for an editbox uicontrol when the text exceeds the control’s width, we can use the TipWhenTruncatedEnabled property (or its corresponding setTipWhenTruncatedEnabled() method). This will display a tooltip with the editbox contents if the string is shown truncated. This saves the user having to scroll through the control to see its contents. I often use this for edit controls that may contain long path names:
hEditbox(1) = uicontrol('Style','edit','Units','norm','Pos',[0.1,0.8,0.4,0.05], 'String','Too Short'); hEditbox(2) = uicontrol('Style','edit','Units','norm','Pos',[0.1,0.7,0.2,0.05], 'String','Long Enough to Display a Tool Tip'); drawnow; jEditbox1 = findjobj(hEditbox(1)); jEditbox2 = findjobj(hEditbox(2)); set(jEditbox1,'TipWhenTruncatedEnabled',true); % property-based alternative javaMethod('setTipWhenTruncatedEnabled',jEditbox2,true); % method-based alternative
The TipWhenTruncatedEnabled property property is also available for multi-line editboxes, but has (obviously) no effect when scrollbars are present. Also note that setting the TipWhenTruncatedEnabled property to true overrides any previous tooltip that might have been set for the editbox.
Finally, note that the TipWhenTruncatedEnabled property can also be set for the editbox component of popup-menu (aka drop-down) controls, after they have been set to be editable using their Java Editable property (note that both properties are false by default for Matlab uicontrols). In the following screenshot, the drop-down’s editbox component contained an HTML snippet, that is shown unformatted within the edit-box and HTML-formatted in the de-truncated tooltip:
Situation 3: Controlling tooltip timing
As you have probably noticed, there is a slight delay between the time your mouse enters the control and when the tooltip actually appears. If you display a tooltip over a control for sufficiently long the tooltip will then disappear. Sometimes the default delays are too slow or fast for your application. These times can be controlled through the javax.swing.ToolTipManager. The ToolTipManager sets these parameters globally (including for your Matlab desktop components), but they are not persistent between sessions.
Some examples using the ToolTipManager:
btn = uicontrol('String','Button','Tooltip','This is a button.','Pos',[100,100,75,25]); txt = uicontrol('Style','edit','String','Edit Text','Tooltip','This is editable text','Pos',[100,50,75,25]); tm = javax.swing.ToolTipManager.sharedInstance; %static method to get ToolTipManager object initialDelay = javaMethodEDT('getInitialDelay',tm); %get the delay before display in milliseconds (=750 on my system) javaMethodEDT('setInitialDelay',tm,0); %set tooltips to appear immediately dismissDelay = javaMethodEDT('getDismissDelay',tm); %get the delay before the tooltip disappears (=10000 (10 sec) on my system) javaMethodEDT('setDismissDelay',tm,2000); %set the dismiss delay to 2 seconds javaMethodEDT('setEnabled',tm,false); %turns off all tooltips in system (including the Matlab desktop) javaMethodEDT('setEnabled',tm,true); javaMethodEDT('setInitialDelay',tm,initialDelay); javaMethodEDT('setDismissDelay',tm,dismissDelay);
Note that I have made extensive use of the undocumented built-in javaMethodEDT function to execute Java methods that affect Swing components on the Swing Event Dispatch Thread (EDT). I plan to write about EDT following my next post on event callback chaining.