Animated busy (spinning) icon

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:

Sample usage of an animated spinning icon

Sample usage of an animated spinning icon

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

Animated spinner icon

Animated spinner icon

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:

BusyAffordance started... (animated spinning icon)

BusyAffordance started...
(animated spinning icon)

   
...stopped (PaintsWhenStopped = false)

...stopped
(PaintsWhenStopped = false)

   
...stopped (PaintsWhenStopped = true)

...stopped
(PaintsWhenStopped = true)

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

ProgressBarDialog with animated BusyAffordance

ProgressBarDialog with animated BusyAffordance

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.

Categories: GUI, High risk of breaking in future versions, Icons, Java, Undocumented feature

Tags: , , ,

Bookmark and SharePrint Print

51 Responses to Animated busy (spinning) icon

  1. Aurélien says:

    Hi Yair!

    How do you close or delete safely the above ProgressBarDialog with animated BusyAffordance ?

    Thanks
    Aur

  2. peinal says:

    How to make the Figure just frame the spinning icon (in size)?

  3. AB says:

    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.

  4. me says:

    Hi Yair,
    How could I delete the BusyAffordance “button”, or set it invisible? (not just stop it)

    Thank you!

  5. Johny says:

    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?

  6. Vishal Rane says:

    Doing

    jObj.setBusyText('All done!');

    before stopping the object ensures setBusyText property is updated in the figure.

  7. Dani says:

    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:

      jProgressFrame = [];
      jFrames = java.awt.Frame.getFrames;
      for idx = 1 : numel(jFrames)
          if strcmpi(jFrames(idx).getName, 'ProgressBarDialog')
              jProgressFrame = jFrames(idx);
              break;
          end
      end

      Note that this is a Java Frame, not a Matlab figure window.

      To modify the title simply update the Frame’s Title property:

      jProgressFrame.setTitle('New title...')
  8. Charlie says:

    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.

  9. Shannon says:

    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.

  10. Aurélien says:

    It seems that the ProgressBarDialog class does not exist anymore in R2014b Prelerelease …

  11. Hugo Mendonça says:

    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!

  12. Iain D says:

    Are there any significant advantages to this approach over simply changing the pointer to a spinning circle using code similar to the method below?

    set(handles.GUI_main, 'pointer', 'watch'); drawnow;
    %code in here that does something...
    set(handles.GUI_main, 'pointer', 'arrow')

    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.

  13. Arjen says:

    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?

  14. Kathi K says:

    Hey Yair,

    I wondered how you managed to get the animated icon in the cell of a table(?) ?
    When using

    jTable.setValueAt(str,1,1)

    str being a html content, my gif is static; no animation :(

    Appreciate your help,
    Kathi

  15. Robert Moss says:

    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.

  16. scmg says:

    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 after jObj.start. Also, ensure that the component is visible onscreen when you call jObj.start.

  17. Paul says:

    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 !

    • Yair Altman says:

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

  18. Tommie Heard says:

    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.

  19. Alex says:

    Hello,

    Anyway I can change the background color of BusyAffordance? I found the method setBackground under getComponent but it doesn’t work.

    No method 'setBackground' with matching signature found for class
    'com.mathworks.widgets.BusyAffordance$1'.
    

    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 on BusyAffordance I do not know.

    • Alex says:

      Well, I did this:

      obj.jObj = com.mathworks.widgets.BusyAffordance(Size32x32, 'Processing...');
      javaObj = handle(obj.jObj.getComponent);
      javaObj.setBackground(java.awt.Color.red);

      but It didn’t change the color. Gotta keep trying. Thanks Yair for your quick response, by the way.

    • Alex says:

      Actually it does work! I was changing the color in two difference places. For future references, to change the BusyAffordances background color use this:

      jObj.getComponent.setBackground(java.awt.Color(0.8, 0.8, 0.8));
  20. Al says:

    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:

    jObj.getComponent.setForeground(java.awt.Color(1, 1, 1));

    But this didn’t work and checking

    jObj.getComponent.getForeground

    Returned

    java.awt.Color[r=26,g=26,b=26]

    Thanks
    Al

    • Al says:

      Correction: getForeground Returned

      java.awt.Color[r=255,g=255,b=255]

      (As expected but no change to font color seen)
      Also tried:

      jObj.getComponent.repaint

      After setting but to no avail
      Thanks
      Al

    • I do not know that this is possible with BusyAffordance

  21. Richard says:

    Is there a way to create and use a custom spinning icon? if so, how?

  22. Piyush Khajanji says:

    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.

  23. BenBen says:

    Is there a way to get multiple text lines in the jObj.setBusyText? Thanks !

  24. Tobias says:

    Hi,

    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.

  25. Marc says:

    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.

    • Collin Pecora says:

      Marc,

      I don’t understand why, but BusyAffordance uses the MJPanel‘s font to measure the busy text, but uses the UIManager’s Label.font to draw it.
      So, you can do something like below, have not tested on the 2009 and below version.

      jOldFont = javax.swing.UIManager.getFont('Label.font'); % get Label.fontjNewFont = jOldFont.deriveFont(20);                     % derive a new font with size 20javax.swing.UIManager.put('Label.font',jNewFont)        % set Label.font to the new font 
      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
       
      jPanel = jObj.getComponent;       % get the MJPanel jPanel.setFont(jNewFont)          % set the panel's font to the new font 
      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!');
       
      javax.swing.UIManager.put('Label.font',jOldFont) % undo what we changed
    • marc says:

      Thank you very much ! It did the job 😉

Leave a Reply

Your email address will not be published. Required fields are marked *