File Exchange

image thumbnail

multiWaitbar( label, varargin )

version (27.6 KB) by Ben Tordoff
A new "shiny" progress-bar with multiple bars in a single window, time-estimates and more.


Updated 01 Sep 2016

View License

This function provides a new progress-bar (waitbar in MATLAB-speak) with the following features:
* Multiple bars in one window
* Robust to the window being closed
* Time-estimates for long-running tasks
* Completion percentage for long-running tasks
* Control of the color for each bar
* Textured bars (pointless, but nice)
* No need to keep/manage window handles
* Cancel tasks using a return flag or callback function
* "Busy mode" where a bar bounces back and forth
Note that this incurs roughly the same computational overhead as the built-in WAITBAR for low numbers of iterations and usually less overhead for high numbers of iterations.
Requires MATLAB R2009a or above.

Cite As

Ben Tordoff (2020). multiWaitbar( label, varargin ) (, MATLAB Central File Exchange. Retrieved .

Comments and Ratings (87)

Sreeraj S J

Not working in 2019b;
Always showing error for integer sizes somehwere;

Error using ones
Size inputs must be integers.

Error in multiWaitbar>iUpdateEntry (line 554)
bgim = entry.BackgroundCData(:,ones( 1, psize(1)-filled ),:);

Error in multiWaitbar (line 238)
[entries(idx),needs_redraw] = iUpdateEntry( entries(idx), force_update );

Error in waitbartest (line 13)

Frank Han


To get the multiwaitbar working properly with the parallel processing toolbox, please have a look at this example:


Very nervous clicking and moving around of the multiWaitbar leads, in my case, to
Error using ones - Size inputs must be integers.
in line 554.
Changing this line to
bgim = entry.BackgroundCData(:, ones( 1, int32(psize(1))-filled ),:);
fixes this. Maybe update the source if you agree with this finding?

Says : compatible with any release, but there is at least one dependancies to matlab R2013 : flip().
This function does'nt exist or isn't available in previous releases. Take it in consideration for Release Compatibility.

Luca Amerio

Could you add possibility to split all bar into N columns? I need to use a lot of bars, e.g 100, so could be really useful split all bars into 4 columns, with 25 bars for each

Exactly what I needed


The best waitbar ever. Thanks for sharing.



Luca Amerio

There is a big with the cancel button. If you push the cancel button of an entry that has been renamed the Callback returns and error.

I found the error to be in line 455, sub-function iAddEntry. The Callback of the button is indeed defined as
'Callback', @(src,evt) iCancelEntry( src, label )
that doesn't get updated when you use the Relabel option.

You can solve adding
entries(idx).CancelButton.Callback = @(src,evt) iCancelEntry( src, values{ii} );

after line 184
entries(idx).Label = values{ii};


This is an excellent function but I have an annoying issue. The 'busy' setting hangs during long executions like an intensive load() call.

Works very well - only little bug:
if lable has been changed the cancel button no longer works, because the lable was not updated for callback function "iCancelEntry".

To fix this only replace line 184

entries(idx).Label = values{ii};

by the following code:

label = values{ii};
entries(idx).Label = label;
entries(idx).CancelButton = uicontrol( 'Style', 'PushButton', ...
'String', '', ...
'FontWeight', 'Bold', ...
'Parent', FIGH, ...
'Position', [5 5 16 16], ...
'CData', iMakeCross( 8 ), ...
'Callback', @(src,evt) iCancelEntry( src, label ), ...
'Visible', 'off' );

Adam Wyatt

Great function.

Small bug - sometimes gives an error when initializing. Tracked it down to line 554:
bgim = entry.BackgroundCData(:,ones( 1, psize(1)-filled ),:);
Sometimes psize is not an integer. Simply fix is to surround it in a ceil command:
bgim = entry.BackgroundCData(:,ones( 1, ceil(psize(1)-filled) ),:);

Also would be good if we could get a handle to the figure window so that we can control its properties.


Yuyang Wang

Function works like perfect. But here I second Igor, I also noticed a warning about the NARGCHK calling. I tried to use NARGINCHK and NARGOUTCHK to replace it, but I couldn't get them working together with the error function. Anyone knows how it should work?


Jan Keller

Quite cool.


I've just noticed a tiny compatibility issue, related to R2016a prerelease - a warning is thrown each time NARGCHK() is called:

Warning: NARGCHK will be removed in a future release. Use NARGINCHK or NARGOUTCHK instead.

This is a great tool to use! It's working wonderfully, however I too had the same issue with percentages not updating at the start of a progress bar's movement similar to what David (04 Nov 2013) and Adam (18 June 2014) had described. I have found a fix:

In situations where ONLY 'Increment' or 'Value' are used to update the progress bar, the variable named 'force_update' is not set to "true" (see lines 158-168), however 'needs_update' is set to true.

Scroll down to line 237, where we see the function iUpdateEntry is called if 'needs_update' is true, which it is in this scenario, because I'm either updating the value or incrementing it. We see here that the variable 'force_update', which is still false, is being passed to function iUpdateEntry.

Scroll down to line 629, located within iUpdateEntry, and we see two possible culprits for the percentage completed not being updated.

Possibility 1. In function iUpdateEntry, the variable 'force_update' is passed to variable 'force', and we see in line 629 that the 'if statement' will not enter because 'force' is still false.

Possibility 2. Line 629's 'if statement' is also looking to see if (elapsedtime > minTime) in order to enter into the statement commands. However, minTime is set to default 3 seconds, which means that if you're updating your value or incrementing it before 3 seconds is up, the 'if statement' is satisfied by neither of the two conditions. Therefore, lines 631 and 632 are not executed (these are responsible for updating the user input string appended to the percentage completed).

SOLUTION: I simply commented out lines 629 and its respective 'end' on line 635 in order to 'force' MATLAB to run through and update variable 'labelstr' if the previous 'decval' is not equal to 'lastdecval'. So far so good!

Version I referenced: 06 Oct 2014


I used a 3 layer nested for loop (3 waitbars with 3 colors) but the expected time (ETA) is not computing correctly. It jumps from smaller numbers to bigger numbers and then jumps back.

Wei Yap Tan

A very nice waitbar! I would personally wish for the ability to make the waitbar in focus again after my parent GUI updated its plot.


Best one supporting nested for loops out in FE. However, seems time estimation is seriously wrong while multiple waitbars in nested for loops are used.

The command "flip" was introduced in R2013b as a more efficient version of "flipdim". I suggest to include a try-catch construction which first tries "flip" and in case of an error uses "flipdim" (or "fliplr", in the case of flip(M,2) as it is used here).

[The more 'clean' way of using "verLessThan" is extremely slow (~5.000x slower than try-catch).]

I had an error with call of flip() r2012a - "Undefined function" and replaced that line.

Excellent utility! There is a bug however with 'ResetCancel' (noticed already by Bryant Svedin in 2013). In order for it to work as intended, I'd suggest adding at line 196 "needs_update = true;"; otherwise, the new value of entries(idx).Cancel is not saved in AppData.

Luis Camilo

Hi Ben, you have a new version so that you can integrate your code in a GUI?


The speed-up compared to the built-in waitbar is great, thank you!

Adam Wyatt


I observed the same bug (or similar) as David - 04/11/13 to do with not updating the % correctly.

A couple of additions would be nice:
1) Option to return the figure handle - useful in some circumstances (e.g. to force the window to the front / edit some properties.
2) To be able to embed the multiWaitbar inside a different parent object (e.g. user defined figure / panel).


I like this tool a lot and managed to get it to work very easily. However, I wanted three different processes to run simultaneous (as now one function has to terminate before the next starts calculation so there is always only one waitbar progressing) so I am using the parallel computing toolbox and run three functions in batch. Now the progress on the multiwaitbar is not updated anymore so there is no means to check how far the process has progressed. Because it takes a long time, this is really required for my application so I was wondering if it was possible to make the multiwaitbar to work when using batch to run the function where it is called. If this is inherently impossible, please let me know so that I do not spend any more time on it. Any suggestion would be welcome to tackle this problem in a different way.

Nikolay S.

Very nice visually, and easy to use. The time measurement, is not very exact. For fast iteration counting (percentage) and time estimation start a bit late...

Amir Pasha

Amir Pasha

Great Job!!!


Very useful, thank you... but there might be a bug in the current version:
In some cases, when I change the value, the bar changes, but the percent-value does not...

many thanks,

try this as an example:

multiWaitbar( 'Task 1', 'Value', 0);
pause(1.5); multiWaitbar( 'Task 1', 'Value', 0.15); % Task 1 still at (0%)
pause(1.5); multiWaitbar( 'Task 1', 'Value', 0.3); % Task 1 still at (0%)
pause(1.5); multiWaitbar( 'Task 2', 0.5, 'Color', 'b' ); % Task 1 gets (30%)
pause(1.5); multiWaitbar( 'Task 1', 'Value', 0.45 ); % Task 1 gets (45%)
pause(1.5); multiWaitbar( 'Task 1', 'Value', 0.6 ); % Task 1 gets (60%)
pause(1.5); multiWaitbar( 'Task 2', 'Value', 0.75 );
pause(1.5); multiWaitbar( 'Task 1', 'Reset'); % Task 1 still at (60%)
pause(1.5); multiWaitbar( 'Task 1', 'Value', 0.2); % Task 1 still at (60%)
pause(1.5); multiWaitbar( 'Task 2', 'Close' ); % Task 1 gets (20%)
pause(1.5); multiWaitbar( 'Task 1', 'Close' );

Brian Katz

Very useful, especially the time estimator. Well done, and well supported.


Very nice and useful progress bar!
Good point there Marc G. I would also like to change the label of each progress bar. I wanted to display the elapsed time.
Looking forward to your update!

Ben Tordoff

I've submitted an update that fixes the interp issue, centres the window and adds a 'relabel' command. It should appear here within the next few days.


Marc G

Thanks! Very useful and easy to use.

I would love to be able to update the label of a given entry (for example to be able to give more information like "Simulation in progress... [Current year: 2012 / Current month: 10]") without destroying it and recreating it.

I am thinking to a command like "UpdateLabel".

I understand that it would not be a straightforward change to the code, given that it seems that the Label is used to define the entry. But if I find enough time later I may try to dig into the code and decorrelate the label text from the entry in order to make it updateable.

Thanks again!


Hm,since R2013b Matlab complains about interpolation method:

>> multiWaitbar('aaa',1)
Warning: INTERP1(...,'CUBIC') will change in a future release. Use INTERP1(...,'PCHIP') instead.
> In interp1>sanitycheckmethod at 283
In interp1>parseinputs at 420
In interp1 at 81
In multiWaitbar>iMakeColors at 389
In multiWaitbar>iAddEntry at 413
In multiWaitbar at 128

It looks like this file needs another update...

It is great!, but, why the progress bar is not centered in the screen?, I think it is better if you add the following few lines at beginning of the figure creation and in the function iCreateFig

FigSize = [300 800]; % figure size
ScreenSize = get(0,'ScreenSize');
xpos = ceil((ScreenSize(3)-FigSize(2))/2); % center the figure on the screen horizontally
ypos = ceil((ScreenSize(4)-FigSize(1))/2); % center the figure on the screen vertically
fobj.Position = [xpos, ypos, sz(2), sz(1)];


Really nice piece of code. I was wondering though - is there a way to reposition the bar window? On my screen it pops up right over the command line so it hides any output from the running script, I can move it but I would like to make it automatic. Thanks.

I love this, but I am having trouble with the cancel function. I can't get the 'ResetCancel' to work. Example

multiWaitbar( 'Task 1', 0, 'CanCancel', 'on' );
for ii=1:15
abort = multiWaitbar('Task 1', ii/15);
if abort
yesno = questdlg('Are you sure you want to cancel?', ...
'Cancel', ...
if strcmp(yesno,'Yes'), break;
pause( 1 )
multiWaitbar('Task 1', ii/15, 'ResetCancel');
pause( 1 )
multiWaitbar( 'Task 1', 'Close' );

It gives the following error when this code is run and no is selected after trying to cancel.

??? Error using ==> multiWaitbar>iParseInputs at 276
Additional properties must be supplied as property-value pairs

Error in ==> multiWaitbar at 145
[params,values] = iParseInputs( varargin{:} );


Suraj Kamya



This waitbar is great!
To make the window always appear in the center of the screen, I modified the 'Resize' section as shown below since I couldn't figure out a way to get the figure handle of the waitbar. Is there any simpler way to do this? I'm new to MatLab, so I'm suspecting that I might have over complicated things.

% Resize
fobj = handle( f );
screenSize = get(0, 'ScreenSize');
xCord = screenSize(3)/2 - 180;
yCord = screenSize(4)/2 - 21;
fobj.Position(1:4) = [xCord yCord 360 42];
setappdata( fobj, 'ProgressEntries', [] );


Ben Tordoff

Good spot Dan, I'll add that in the next update - thanks!

Dan K

Very nice, albeit with one bug. If one has defaultWindowStyle set to docked, you get some very interesting effects... I would suggest adding:


At line 293

Ben Tordoff

Hi Jerome, that's a good suggestion. Ideally it should update the labels whenever they change (which may be more often than the bar updating) but it seems that the computation of the remaining time is itself worth avoiding. Avoiding updating the labels when the bar hasn't moved is a reasonable compromise. I'll add it.

Fantastic tool!
I think it could be improved further by limiting the call to remaining time calculation.

Adding 'if updated' between the remaining time block in iUpdateEntry makes thing much faster when using this in a large loop.

Excellent! It was just what I needed and the example included sets it right up!


Fantastic and easy to use.


Works great!!! Thanks.

Ben Tordoff

Hi Paul, this is going to take a bit of explaining, but to cut to the chase, try this:

function testme
multiWaitbar('One', 0, 'CanCancel', 'on', 'CancelFcn', @callback );
multiWaitbar('Two', 0, 'CanCancel', 'on', 'CancelFcn', @callback );

cleanupFigObj = onCleanup(@() multiWaitbar('CloseAll'));

function callback(a,~)
disp( ['Cancel ',a] )

The main problem you were hitting is that the anonymous functions you use in the callbacks (i.e. the @(a,b)) cause the "cleanup" object to be held in-scope (i.e. it never gets deleted and therefore never "cleans-up"). If you use internal or external functions for your callbacks rather than nested or anonymous ones (i.e. functions defined outside of the function you're working in) then this doesn't happen.

That's probably clear as mud, but try the code and let me know. Hopefully this restriction won't be too onerous.

Cheers. Ben


Ben, thanks for the file, I really like your implemntation of the progress bar. I'm currently using it for a 2-part progress bar, however I'm having difficulty implementing the cleanup function. Is it possible to use a variant of

cleanupFigObj = onCleanup(multiwaitbar('CloseAll'));

to close the multiwaitbar upon function exit? I was able to close one (and only one) of my two progress bars using a function handle to multiwaitbar such as:

fh = @multiWaitbar;
fh('One', 0, 'Color', [1.0 0.4 0.0], 'CancelFcn', @(a,b) disp( ['Cancel ',a] ));
fh('Two, 0, 'Color', [0.1 0.5 0.8], 'CancelFcn', @(a,b) disp( ['Cancel ',a] ));
cleanupFigObj = onCleanup(fh('CloseAll'));

Do you have any suggestions? Thanks.


Ben Tordoff

The simple answer would be:

for uio=1:480

I wouldn't worry too much about calling it lots of times - it doesn't update unless the progress bar would visibly change. If you find it is taking a measurable amount of time then surround the inner call with something like

if mod(uio,10)==0

That will make it update every tenth iteration of your outer loop.

Cheers. Ben


So I played around with it and i ran it in the command window a couple of times.
I have another question.How can i use it within a for-loop
For eg:
My for loop structure is shown below.Now since there are 480 times this loop is going to be run.How can i add your multiwaitbar showing an increment of 10% after 'uio' computes the loop every 48 times.

To elaborate more.
when uio = 96 (finished) multiwaitbar should show 20%
when uio = 192 (finished) multiwaitbar should show 40%

for uio = 1:480
for i = 1:uio
for j = 1:num_periods
if time(i,1)>= ((time_per).*(j-1)) && time(i,1) < (time_per*(j))
travel_column(uio)= j;



Many thanks for your assistance.


Hi Ben, I am just trying to use it for its main purpose i.e
to show it while something is running.

Now lets say I have 10 blocks(parts) of code which more importantly are not in a for-loop structure and after every part i want to popup the multiwaitbar such that it shows the progress by an increment of 0.1 or 10%.

How can I achieve this in my GUI Window??

Ben Tordoff

Hi Karan, when you say "integrate" what do you mean? Are you just trying to show it/hide it whilst something is running or are you trying to embed the bars themselves into your GUI window? (the latter isn't possible in any sane way right now). If you can explain a bit more I (or someone else here) can probably give you some guidance.


Hi I am making my first GUI and I would like to add this in my GUI, however the code in this tool is way beyond my knowledge in matlab.
It would be really appreciated if somebody can give me some tips on how to integrate/use it successfully with my GUI

A very well done function! Very simple to use, yet with many options and really looking good!
Great job!






Well, I think I got it.

One need to add getappdata(..) to the very end of iAddEntry(..)
if strcmpi( get( parent, 'Visible' ), 'on' )
iRedraw( parent, [] );
set( parent, 'Visible', 'on' );
entries = getappdata( parent, 'ProgressEntries' ); % added to keep background
end % iAddEntry

Nice, stable and simple.

Awesome waitbar.

To prevent the waitbar from jumping back to its original position (in matlab 2011a and maybe other editions) I added drawnow to the first few lines of the iRedraw function.

fobj = handle( fig );
p = fobj.Position;



Fantastic work. Thank you.


Ben Tordoff

Hi Igor, thanks for the comments. I've just submitted a new version that fixes the focus-grabbing - that was a bug, sorry. This should appear here within the next day or two. Cheers. Ben


Great job!
yet lastest (Updated 29 Jul 2010) version steals focus where previous one didn't... so I prefer to use previous one...
also, as a suggestion... To reduce overlap in loops like
for ....
multiWaitbar( label, varargin )
for ...
multiWaitbar( label2, varargin2 )

inner multiWaitbar(...) may be replaed with something like

function multiWaitbarT( varargin )

persistent multiWaitbarT_tic


if (~any(res)) ||...
isempty(multiWaitbarT_tic) ||...


this seem to reduce overlap up to ~20x, and can be useful if execution time varies strongly in test/release runs....



For example, this code:


%% strict

for i=1:N
multiWaitbar('l1',i/N,'Color', [0.2 0.9 0.3]);
for j=1:N
multiWaitbar('l2',j/N,'Color', [0.2 0.9 0.3]);
disp(['strict:' num2str(toc(t))]);

%% T

for i=1:N
multiWaitbar('l1',i/N,'Color', [0.2 0.9 0.3]);
for j=1:N
multiWaitbarT('l2',j/N,'Color', [0.2 0.9 0.3]);
disp(['T:' num2str(toc(t))]);
results in:


Thanks for great tool!

Ben Tordoff

Hi Sander, you're right. I forgot to turn off integer handles, so even though the figure handle is not visible it can still be clobbered. This is fixed in the update I'm about to submit. Should be with you within the next day or two.


Hi Ben,

Look great, works great but.....
I think there is a small bug.
When a figure in a loop is called h = figure(1) then the progress bar disappears (were h is whatever handle). Naming a figure: h = figure(10) prevents this bug from happening.

then (ofcourse) looping a figure: h = figure(j) has this problem also

it maybe your choice but "close all" also closes the progress bar. I would let your build in LABEL comment close do this and not the general close all. But that is a choice...I think the previous is a bug?


Works Perfect. Thank you

Ben Tordoff

Hi Gordon,

There are two ways to set the value and I think your code mixes the two - you are incrementing by ever larger factors! Because you increment by 'k/1000' rather than '1/1000' your total value by the end will be over 500, rather than 1. Here are the two ways the multiWaitbar should be used:

% Set value directly
for k=1:1000
multiWaitbar( 'Task 1', k/1000 )

% Set by increment
for k=1:1000
multiWaitbar( 'Task 2', 'Increment', 1/1000 )

Let me know if you have problems with either of these, or I have missed some subtlety in the problem you're having.



Looks good, but It doesn't seem to work well with small increments, unless I am missing something.
For the code below, the progress bar finishes much earlier than the main loop.

multiWaitbar( 'Task 1',0);
for k=1:1000
multiWaitbar( 'Task 1','Increment',k/1000 );
fprintf('%d / %d <%1.4f>\n',k,1000,k/1000);

Jim Crozier

Joseph Kirk

This is *exactly* what I was looking for! I wanted a waitbar that could get called by various functions (so that I could have an "overall progress" bar along with progress updates for various subroutines) without having to pass handles around everywhere. This does all that and more... I'm really impressed (and glad I checked the File Exchange before attempting my own version). Rate it a 6!


Updated license

* Fix bug with ResetCancel
* Improve compatibility with MATLAB R2014b

* Allow labels to be changed ('relabel')
* Use 'pchip' interpolation instead of 'cubic'

* Fix updating of percentage indication
* Fix ResetCancel command

* Don't update text labels if bar didn't move. This gives around a 20% speed-up in some cases.

* Add ability to set a bar into "busy" mode where it bounces back and forth

This update should hopefully fix some of the long-standing graphical glitches when moving or resizing the window. Thanks to Igor for testing this!

* Don't grab focus unless currently hidden

* Add ability to cancel using return flag or callback function
* Don't lose bar properties if the window gets closed
* Prevent the window being accidentally clobbered

Fix highlight markers at 10% intervals (were wrong way round)
Shade background

2010-05-12: Significant (~20%) speed improvement

MATLAB Release Compatibility
Created with R2009b
Compatible with any release
Platform Compatibility
Windows macOS Linux

Inspired: waitbarTimeRemaining, CATT2Matlab