File Exchange

image thumbnail


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


Updated 04 Aug 2020

View Version History

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 (2021). multiWaitbar (, MATLAB Central File Exchange. Retrieved .

Comments and Ratings (96)

Chang hsiung

it works perfectly now !!!


I tried to reproduce the problem with the non-integer sizes that I reported with the previous version that I use (probably, not sure since the .m file does not contain the version number). Turns out that it can be triggered by starting the multiWaitbar and then minimize the horizontal width of its figure by dragging the right figure edge as far as possible to the left. And yes, I do have display scaling on in Windows 10 (150%).
Then I tried to trigger it while using your most recent update. Not sure it's gone for good, but my initial tests did not trigger it any more.

Ben Tordoff

Hi Chang, I've just uploaded an updated version that tries to fix the non-integer size values, but also returns you the figure handle so that you can change the position etc. Please give it a try! e.g.

>> [~,figh] = multiWaitbar(...);
>> figh.Position(1:2) = [100 100]

Chang hsiung

Is there a way I can set the 'position' for this wonderful waitbar ?

Chang hsiung

Ben Tordoff

Thanks to those who've reported and isolated the problem with non-integer sizes. I've not been able to observe this myself so I'm wondering if a UI widget size that is a fraction of a pixel is specific to a high-DPI display (which I don't have)? In any case the suggested fix (calling ceil) seems reasonable and I'll try to include it in a future update. I've recently fixed a number of other minor issues that people have reported so please do continue to report problems and make suggestions for improvements - they are all welcomed!


Vlad Atanasiu

Mythical function!
If your standalone application hangs it might be because a bug in multiwaitbar. The workaround by Adam Wyatt of 28 Mar 2016 may fix it.

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?

Arthur Hamelin

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

Andrea Stevanato

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

Genevieve Le Houx

Exactly what I needed


siddharth rawat

The best waitbar ever. Thanks for sharing.



Florian Büttner

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.

Klaus Heller

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.

William Leismer

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

Nikolay Cherkasov


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.

Jonas Asprion

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).]

Timo Dörsam

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

Timo Dörsam

Andrei Veldman

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...

Mohammed Diab

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)];


Right Grievous

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.

Bryant Svedin

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{:} );

Alexandre Willame


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.

Jerome Lecoq

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.

Sebastian Holmqvist

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


Kevin Claytor

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

Andrey Babkin

Nice, stable and simple.

Jeroen van Nugteren

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.


Sander van Delden

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?


Bryant Svedin

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

John de Leon

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!

MATLAB Release Compatibility
Created with R2020a
Compatible with R2014b and later releases
Platform Compatibility
Windows macOS Linux

Inspired: Ninox, waitbarTimeRemaining, CATT2Matlab

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!