Displays a tooltip-sized waitbar beneath uicontrols, and is animated. Inspired by "About Face", similarly to my other tooltip submission.
toolTipWaitBarHandle = tooltipwaitbar(hObject)
Generates a waitbar below a uicontrol (hObject). Returns a 4 element array for the static text boxes which make up the waitbar. (1) is the progress bar itself, (2) is the background to the waitbar, (3) is the border, and (4) is a UIContextMenu (right-click menu) that can be used which can hide the waitbar, and also gives information on the steps going through (it logs changes of the message using updatetooltipwaitbar). All can be modified using standard set/get notation. For example, change the colours with:
Progress bar: set(toolTipWaitBarHandle(1), 'BackgroundColor', 'red')
Progress background: set(toolTipWaitBarHandle(2), 'BackgroundColor', 'white')
Border: set(toolTipWaitBarHandle(3), 'BackgroundColor', 'black')
... = tooltipwaitbar(hObject, progress)
Pre-defines a progress level of the waitbar, where the progress is any number from 0 to 1, or, from 0 to 100 (whichever it is is dynamically selected). If left empty, the default is 0.
... = tooltipwaitbar(hObject, progress, message)
Also supplies a message which appears in the ToolTip for the text box. This can be empty (the default), or a string.
... = tooltipwaitbar(hObject, progress, message, useContextMenu)
If useContextMenu evaluates to false (the default is true), the context menu is disabled. If useContextMenu is the handle to a uicontext menu object, then this can be used instead. CAUTION: This will error if you accidentally supply the number to a uicontrol that is not a uicontextmenu. It is recommended this is converted to a logical beforehand if possible.
... = tooltipwaitbar(hObject, progress, message, useContextMenu, usePercentLabel)
If usePercentLabel evaluates to true (the default is false), the
percent label is used. This is a % label at the right alignment of the
progress bar, in white.
... = tooltipwaitbar(hObject, progress, message, useContextMenu, usePercentLabel, abortAction)
AbortAction specifies what to do when the user clicks on abort.
Because of the way it works, the process can only be aborted the next time a callback tries to update the waitbar (e.g. in a loop). It can be true, 'error', or false. If true, an abort status flag (retrieved later, see how to update the waitbar) is changed. If 'error', then the waitbar will deliberately error after the waitbar has been redrawn as normal. If false (the default), nothing happens.
To change the label colour:
set(toolTipWaitBarHandle(1), 'ForegroundColor', 'yellow')
To change the label alignment:
set(toolTipWaitBarHandle(1), 'HorizontalAlignment', 'left')
To change the font size (8 is the default in MATLAB):
set(toolTipWaitBarHandle(1), 'FontSize', 10)
abortStatus = tooltipwaitbar(toolTipWaitBarHandle, progress);
Updates the progress of the waitbar generated using tooltipwaitbar. If an output argument is supplied, the current abort status is given.
tooltipwaitbar(toolTipWaitBarHandle, progress, message)
Updates the waitbar, as well as the status message in the UIToolTip, and if the context menu is on, updates that too. If you only want to change the message, progress can also be empty ().
Removes the waitbar from the figure.
More than one tooltip can be used on the same uicontrol without issue, as long the handles are stored properly (the most recent one will be on top of the stack. No other data is stored. The waitbars stack rather nicely too when a tooltipwaitbar is slaved to another tooltipwaitbar, which makes for some quite interesting visual effects. The tooltipwaitbar is implemented as a series of overlapping text boxes rather than axes/patch objects because axes are always on the bottom of the UI element stack; if there are any other uicontrols nearby, the text object is obscured. The context menu to hide the waitbar merely makes it invisible; it may cause problems later otherwise when other functions attempt to clear up.
The test GUI I use for new features is also bundled.
% create a dummy GUI
hObject = uicontrol('Style', 'pushbutton');
% create waitbar
ttwb = tooltipwaitbar(hObject, 0, 'Starting...');
n = 1;
x = 3;
% simple loop
for m = 1:10 ^ x
n = n + m;
% update waitbar
tooltipwaitbar(ttwb, m / 10 ^ x);
% finish at end
% clear up
clear('ttwb', 'n', 'm', 'x', 'hObject')
I like it better now: it works correctly if you don't abuse the syntax too much, and provides explanatory error messages if you do; The code is well documented and indented, enabling a very easy reading.
I like the implementation use of three overlapping empty-text uicontrols with different background - an innovative alternative to what would normally be done with axes and a patch object (which are admittedly more cumbersome/heavy).
I think this utility, although useful as-is, could be improved further. Here are a few ideas:
1. Enable the context-menu by default (currently off by default - why?)
2. Provide sample usages in the main help comment (for example, modification of the progress bar color, addition of percentage labels etc.)
3. Combine the 3 sub-functions into a single m-file with a single interface. For example: calling tooltipwaitbar with a negative progress to delete the waitbar; calling tooltipwaitbar with its own handle to update the progress value.
4. Accept percentage progress values (between 0-100), not just 0-1 values
5. The main function is fairly large (>200 lines) - I would break it into sub-functions for readability.
6. enable accepting a context-menu handle (not just a true/false flag).
7. There are quite a few other waitbar implementations on the FEX - if you take a look you might get some other interesting ideas.
But as I said above, this utility is already useful as-is. An innovative idea and a good implementation. Good work!
While not a 5-star utility in my eyes, it does merit an A+ for innovation and the author's quick response to early feedback; I also wish to offset my original rating.
Looks useful. How 'bout a screenshot?
Excellent idea, and it looks very nice. However, I encountered several problems:
Firstly, the function demands a third (message) input parameter, which you forgot to mention in your description above. Also, the function returns 3 handles (not 1), and I could not use them to update the waitbar progress.
The code itself could use a more detailed help section, with detailed explanation of usage and input/output arguments.
Finally, I suggest adding a tooltip (perhaps with the supplied message parameter?) and context menu (to dismiss the waitbar).
I think that once these issues are fixed, this could be a very popular and highly-rated utility. I will keep a lookout and be happy to amend my rating at that time.
Again - top marks for a great innovative ideas.
Combined the existing 3 files into one, so syntax has changed significantly, added support for a percent label, and for aborting the task.
Modified to reflect the fact that UIContextMenus cannot be the children of uipanels.
Lots of recoding and tidying up - it now makes much more sense. Added some better documentation in the header. As Yair suggested, The message now gets added to a tooltip, and a context menu can be enabled so the user can hide the waitbar away.
Forgot to include a helper file (getposition).
Inspired: Automated patch clamp