Matlab includes a wide variety of internal widgets (GUI components) that could be very useful in our GUIs. One such widget is an animated spinning icon, which is often used by Matlab itself and numerous toolboxes to illustrate a running task:
One of the internal widgets that are readily-available for use in our Matlab GUI and displays a similar (but not identical) spinning icon is
BusyAffordance
, which is included in the built-in com.mathworks.widgets
package. BusyAffordance
creates a visible panel with an animated spinning icon and optional text label as long as the panel’s object is in the “started” mode (the mode can be started/stopped numerous times).The usage is very simple:
try % R2010a and newer iconsClassName = 'com.mathworks.widgets.BusyAffordance$AffordanceSize'; iconsSizeEnums = javaMethod('values',iconsClassName); SIZE_32x32 = iconsSizeEnums(2); % (1) = 16x16, (2) = 32x32 jObj = com.mathworks.widgets.BusyAffordance(SIZE_32x32, 'testing...'); % icon, label catch % R2009b and earlier redColor = java.awt.Color(1,0,0); blackColor = java.awt.Color(0,0,0); jObj = com.mathworks.widgets.BusyAffordance(redColor, blackColor); end jObj.setPaintsWhenStopped(true); % default = false jObj.useWhiteDots(false); % default = false (true is good for dark backgrounds) javacomponent(jObj.getComponent, [10,10,80,80], gcf); jObj.start; % do some long operation... jObj.stop; jObj.setBusyText('All done!'); |
Note how I’ve used the javacomponent function to place the BusyAffordance
object onscreen, at position 10,10 of the current Matlab figure, and gave it an initial size of 80×80 pixels.
When the object is stop()ed, the icon and label are removed by default, but can be displayed un-animated (non-spinning) via the PaintsWhenStopped property:
The small-icon (16×16) variant of the
BusyAffordance
control is used by another internal Matlab component, ProgressBarDialog
. This control presents an animated progress-bar dialog window, similar to Matlab’s built-in waitbar function but with an animated busy icon:
d = com.mathworks.mlwidgets.dialog.ProgressBarDialog.createProgressBar('test...', []); d.setValue(0.75); % default = 0 d.setProgressStatusLabel('testing...'); % default = 'Please Wait' d.setSpinnerVisible(true); % default = true d.setCircularProgressBar(false); % default = false (true means an indeterminate (looping) progress bar) d.setCancelButtonVisible(true); % default = true d.setVisible(true); % default = false |
For those interested, the 16×16 animated GIF used here is spinner.gif, which can be found in %matlabroot%/java/jar/mlwidgets.jar (remember that JAR files are simply ZIP files, so they can be opened in WinZip/WinRar etc.).
BusyAffordance
also includes a 32×32 icon which is not available as a separate icon file. Also, the BusyAffordance
spin direction is reversed compared to the spinner icon. From this we learn that BusyAffordance
probably creates its spinner image on-the-fly (programmatically), rather than use spinner.gif.For additional information on
BusyAffordance
, com.mathworks.widgets
and other internal Matlab components, refer to chapter 5 in my Matlab-Java programming book.As with other internal Matlab components, I categorized this feature as “High risk of breaking in a future release“. Still,
BusyAffordance
has existed in its present form since R2010a (and with a slightly different interface for years before then), so there’s a good chance that it will continue as-is in the foreseeable future. Then again, it might be removed as early as the next upcoming release, without prior warning…More advanced animated busy indications, including automated percentage and time-remaining labels, can be specified using
JBusyComponent
, which is a JXLayer decorator that can be applied to any displayable component. In R2013b or newer that use Java7, we can also use the built-in JLayer
class. We can also simply embed the animated GIF image directly in our GUI, as I explained here.In the past I have already shown how to use other internal components in Matlab’s
com.mathworks.widgets
package, including syntax-highlighted labels and text panes that can be embedded in our Matlab GUI.Have you used
BusyAffordance
or some other internal Matlab component in a neat way in your GUI? if so, please do tell us about it in a comment below.
Hi Yair!
How do you close or delete safely the above
ProgressBarDialog
with animatedBusyAffordance
?Thanks
Aur
(or simply click the <Cancel> button…)
Thanks Yair!
How to make the Figure just frame the spinning icon (in size)?
@Peinal – I don’t understand the problem: why don’t you simply resize the figure using its Position property?
Hi Yair,
Why is it that we don’t need to use javaObjectEDT for this spinner icon?
Kind regards,
AB
In general we aught to use javaObjectEDT for all Java components, but since this control is not interactive it makes little difference.
Hi Yair,
How could I delete the BusyAffordance “button”, or set it invisible? (not just stop it)
Thank you!
Thank you very much!
Hi, Yair,
The post is quite useful and thanks!
I put the Busy Widget into a panel so that I can make it invisible simply. But even if I set the panel frame color to “none” (thanks for your other post), the widget’s background frame is still visible. Can we make the background of the widget transparent?
No, but you can set it to any non-transparent bg color:
Doing
before stopping the object ensures setBusyText property is updated in the figure.
Hi Yair!
First of all, congrats for your amazing blog.
I wanted to know whether it is possible to get the “parent figure” (the handle) of the ProgressBarDialog, in order to prevent it from being accidentally closed. I usually create an empty closerequestfcn on the figure handles for this.
Is it also possible to change the title of a ProgressBarDialog?
Thanks in advance!
@Dani – there is no direct way to find the containing frame, but it can be found indirectly:
Note that this is a Java Frame, not a Matlab figure window.
To modify the title simply update the Frame’s Title property:
Excellent post, Yair!
Is it posible to include this spinning icon on a figure created with h=figure(…)?
Cheers!
@Charlie – that’s exactly what I showed in my article for
BusyAffordance
, which is placed in a Matlab figure using the javacomponent function. Run the code in the article text and see for yourself.Excellent work,Yair! And THX for your sharing.
Is it possible to detect whether the Cancel button is clicked? And how to process this click event?
@Shannon – I’m not aware of a way to do this. You will probably need to create your own dialog window for this. It shouldn’t be too difficult, it’s just a few simple controls.
It seems that the ProgressBarDialog class does not exist anymore in R2014b Prelerelease …
Hi, Yair!
First of all, I have to say I have read a few topics of your website and it is amazing! Congrats for it and all your effort to make it possible!
I am a beginner with simulink and I got some problem. I want to display the simulink progress simulation and I am using a fcn block. The alternative to display it in the command view worked perfectly, however this present example with the progress bar have failed.
Do you have any idea how to apply this example in a fcn block in simulink?
Appreciate your help!
Are there any significant advantages to this approach over simply changing the pointer to a spinning circle using code similar to the method below?
As a first time poster and relative newcomer to GUIs in MATLAB I’d like to add that your website is an invaluable resource, many thanks.
@Iain – the difference is that in some case we may want a static spinning icon embedded in the GUI, not just changing the mouse pointer.
Since you suspect that the spinner image is created programmatically rather than it being a gif, would it be possible to control the spinning speed?
Hey Yair,
I wondered how you managed to get the animated icon in the cell of a table(?) ?
When using
str being a html content, my gif is static; no animation 🙁
Appreciate your help,
Kathi
I placed your ProgressBarDialog code above into a little function for my own use. MOST of the time it works fine. SOME of the time, and I can’t figure out what is causing this, all of Matlab will completely hang when calling this function. I happen to be running 2013a. Has anyone else seen this issue? If I put in a break point and step through the code, it all works fine. When I do not put in a break point, it hangs somewhere in the code shown above. Has anyone else had this issue? I’m guessing it’s a Java related thing that I have little control over… feels like a timing issue somehow. It refuses to hang when stepping through in the debugger.
@Robert – this sounds like a plain standard Matlab EDT timing problem, whose solutions I described here and here.
Hi, i’m trying your example for BusyAffordance in a listbox. When the listbox’s CallbackFcn is called, i want to set listbox’s ‘Enable’ to ‘off’, have a spinning circle, do something which take ~ 3sec, stop the spinning circle, then turn on the listbox again. However, at the first time CallbackFcn is called, nothing appears at first, when process finishes, only the ‘All done!’-circle appears. And after that, nothing changes… Can you give me some suggestions? 🙁
I am using R2015a, and
com.mathworks.mlwidgets.dialog.ProgressBarDialog.createProgressBar
also does not exist anymore … cannot try your other example 🙁@SCMG – yes,
com.mathworks.mlwidgets.dialog.ProgressBarDialog
was removed in R2014b.As to why you don’t see the spinning circle, try to add a call to drawnow and
jObj.getComponent.repaint
afterjObj.start
. Also, ensure that the component is visible onscreen when you calljObj.start
.Hi, I’m really interested in using the progress bar in my GUI. I’ve managed to make it appear when clicking on a button thanks to you (that’s great, really !)
However I would love it to appear in my main figure, called hfig, and not in a new one.
Also,is it possible to make it disappear when some action is done ? (a parameter going from 0 to 1 for instance) ?
Thanks a lot !
@Paul – I assume you mean
ProgressBarDialog
– this is a dialog window so it naturally appears in its own window, like all dialogs. If you want integrated progress bars, there are multiple alternatives. You can find some examples in the Matlab File Exchange. Or try this link.Maybe I’ll blog about this someday.
Since
com.mathworks.mlwidgets.dialog.ProgressBarDialog
was removed in R2014b, is there another way to get the spinning progressbar to work? I loved how it worked.Hello,
Anyway I can change the background color of BusyAffordance? I found the method setBackground under getComponent but it doesn’t work.
Thanks,
A.
@Alex – setBackground() is a Java method (function) that accepts Java colors (e.g.
java.awt.Color.yellow
), not Matlab ones. Whether or not this specific setBackground() method has the desired effect onBusyAffordance
I do not know.Well, I did this:
but It didn’t change the color. Gotta keep trying. Thanks Yair for your quick response, by the way.
Actually it does work! I was changing the color in two difference places. For future references, to change the BusyAffordances background color use this:
Is there a way to change the BusyText to a different color?
For example, make the ‘testing…’ and ‘All done!’ text under the busy animation to white?
I tried using:
But this didn’t work and checking
Returned
Thanks
Al
Correction: getForeground Returned
(As expected but no change to font color seen)
Also tried:
After setting but to no avail
Thanks
Al
I do not know that this is possible with
BusyAffordance
Is there a way to create and use a custom spinning icon? if so, how?
Simplest: put an animated GIF as image in a button.
While BusyAffordance and ProgressBarDialog icons cannot be modified externally, but you can create your own animated icon as Malcolm noted or as explained here: http://undocumentedmatlab.com/blog/displaying-animated-gifs (or using one of the other mechanisms that I referenced in my post text above).
How to remove the Background Box/Square after the processing automatically, I am able to set invisible property to text but not Background. Thanks in advance.
Is there a way to get multiple text lines in the jObj.setBusyText? Thanks !
@Ben – I am not aware of any way to set multi-line text in the
BusyAffordance
objectHi,
I’m trying to use the ProgressBarDialog in Matlab R2018a. However, it seems to be missing from the com.mathworks.mlwidgets package.
Do you know if it has been removed completely or just renamed or moved to another package?
Thank you!
@Tobias – I do not have an immediate answer. You can easily open the Jar files (for example %matlabroot%/java/jar/mlwidgets.jar) using WinZip or WinRAR and check this. If you would like me to spend time to investigate this for you, then please contact me by email for private consulting.
Hi,
How could we increase the size of the text below (“testing…”) ?
Thanks
I am not aware of a way to modify the text font. You might have thought that
jObj.getComponent.setFont(jObj.getComponent.getFont.deriveFont(20))
would do the trick, but in fact it just shifts the text label without modifying its font.Marc,
I don’t understand why, but BusyAffordance uses the
MJPanel
‘s font to measure the busy text, but uses the UIManager’sLabel.font
to draw it.So, you can do something like below, have not tested on the 2009 and below version.
Thank you very much ! It did the job 😉