How to use Rhino.UI.ProgressBar in Rhino 8

Hi,

We are in the progress of upgrading our plugin from Rhino 7 to Rhino 8. There seem to be some differences in how the Rhino.UI.ProgressBar works in Rhino 8.

For example, the code below works just fine in Rhino 7. Basically it will show an update message and pause for 500ms so you can see it.

Rhino.UI.StatusBar.HideProgressMeter();
var count = 100;
var message = "Test";
var result = Rhino.UI.StatusBar.ShowProgressMeter(0, 100, message + @$" (0/{count})", true, true);

for (int i = 0; i < count; i++)
{
	System.Threading.Thread.Sleep(500);
	Rhino.UI.StatusBar.HideProgressMeter(); // The line below won't work unless you hide the current message first.
	result = Rhino.UI.StatusBar.ShowProgressMeter(0, 100, message + @$" ({i + 1}/{count})", true, true);
	result = Rhino.UI.StatusBar.UpdateProgressMeter(i + 1, true);
	
}
Rhino.UI.StatusBar.HideProgressMeter();

However, in Rhino 8 this code doesn’t work at all. Reviewed the latest RhinoCommon documentation and developer guides for some clues. It seems that using RhinoApp.Wait() or Eto.Forms.Application.Instance.RunInstance() are need in order to update the correct thread. I’m guessing that something changed to how UI updates are handled in Rhino 8.

The code below has been updated so it works again.

Rhino.UI.StatusBar.HideProgressMeter();
var count = 100;
var message = "Test";
var result = Rhino.UI.StatusBar.ShowProgressMeter(0, 100, message + @$" (0/{count})", true, true);

for (int i = 0; i < count; i++)
{
	System.Threading.Thread.Sleep(500);
	Rhino.UI.StatusBar.HideProgressMeter(); // The line below won't work unless you hide the current message first.
	result = Rhino.UI.StatusBar.ShowProgressMeter(0, 100, message + @$" ({i + 1}/{count})", true, true);
	result = Rhino.UI.StatusBar.UpdateProgressMeter(i + 1, true);
	Eto.Forms.Application.Instance?.RunIteration(); // RhinoApp.Wait() has a similar effect.

}
Rhino.UI.StatusBar.HideProgressMeter();

This does bring the progress panel back again. But there still are some issues with it. If you run it a couple of times you’ll see that it appears to skip some of the ShowProgressMeter updates. In the 100 updates it seems to miss 4-5 of them.

My question is, what is the recommended way to use the ProgressBar in Rhino 8? While the code above is good enough for a patch for now it would be better with something that actually works the way it should. Perhaps this a new bug?

If anyone has a better solution to this I would appreciate your input.

Hi @SK-Structurecraft,

Here is a cheap Python sample:

#! python 3
import Rhino
import scriptcontext as sc
import System

def test_progressbar():
    sn = sc.doc.RuntimeSerialNumber
    low = 0
    high = 100
    percent = False
    Rhino.UI.StatusBar.ShowProgressMeter(sn, low, high, "Starting", True, percent)
    for i in range(low, high + 1):
        Rhino.RhinoApp.Wait()
        System.Threading.Thread.Sleep(100)
        if i == 25:
            Rhino.UI.StatusBar.UpdateProgressMeter("Calculating", i, True)
        elif i == 50:
            Rhino.UI.StatusBar.UpdateProgressMeter("Processing", i, True)
        elif i == 75:
            Rhino.UI.StatusBar.UpdateProgressMeter("Finishing", i, True)
        else:
            Rhino.UI.StatusBar.UpdateProgressMeter(i, True)
    System.Threading.Thread.Sleep(1000)
    Rhino.UI.StatusBar.HideProgressMeter(sn)

if __name__ == "__main__":
    test_progressbar()

– Dale

1 Like

I didn’t know about this feature and I’m intrigued.

When I run your python sample, there is no visible change to Rhinos UI. I don’t see anything popup at all.

I’ve also done a Reset to Current Window Layout to make sure I hadn’t hidden something. Does it matter if I was running your script using the ScriptEditor?

there’s no popup, the progressbar is located in the statusbar (lower end of your screen)

Let me rephrase that, no visible changes anywhere in the Rhino’s UI while running the script.

image

Looks like the UseIconsInStatusBar needs to be True:

image

no, that should not be the case, the reason you are not seeing it is because your Rhino Window is not wide enough.

I only enabled that option without changing the window size and it showed up. I made the wrong observation though only looking for the progress bar to appear. Switching on the Icons took less space that the default Text in the status bar, which allowed for more space to see the progress bar.

Sorry for the false correlation vs causation. :wink:

Thanks for the help! Cool feature!

1 Like

Hi Dale, thanks for the sample. It does look like the simpler version work well. I did try to update that with the same logic we are using where the text updates every iteration.

#! python 3
import Rhino
import scriptcontext as sc
import System

def test_progressbar():
    low = 0
    high = 100
    count = 100;
    message = "Test";
    result = Rhino.UI.StatusBar.ShowProgressMeter(0, 100, message + f" (0/{count})", True, True);
    for i in range(low, high + 1):
        System.Threading.Thread.Sleep(500);
        Rhino.UI.StatusBar.HideProgressMeter();
        Rhino.UI.StatusBar.ShowProgressMeter(0, 100, message + f" ({i + 1}/{count})", True, True);
        Rhino.UI.StatusBar.UpdateProgressMeter(i + 1, True);
        Rhino.RhinoApp.Wait();
    System.Threading.Thread.Sleep(1000)
    Rhino.UI.StatusBar.HideProgressMeter()

if __name__ == "__main__":
    test_progressbar()

It seems that in this case as well it seems to skip some of the text and progress updates. Just run it a couple of times. Is there any way of getting that to show the correct updates every time?

If not we’ll probably just switch to using it in a simpler way.

1 Like

Hi @SK-Structurecraft,

I’m not seeing any skipping here. I’ve cleaned up your code a little - removing the extra hide and show calls.

#! python 3
import Rhino
import System

def test_progressbar():
    low = 0
    high = 100
    message = "Test";
    result = Rhino.UI.StatusBar.ShowProgressMeter(0, 100, message + f" (0/{high})", True, True)
    for i in range(low, high):
        System.Threading.Thread.Sleep(100)
        Rhino.UI.StatusBar.UpdateProgressMeter(message + f" ({i + 1}/{high})", i + 1, True)
        Rhino.RhinoApp.Wait();
    System.Threading.Thread.Sleep(500)
    Rhino.UI.StatusBar.HideProgressMeter()

if __name__ == "__main__":
    test_progressbar()

– Dale

2 Likes

This works great. Looks like the UpdateProgressMeter overload was added in Rhino 8.6. Wasn’t aware of it. Always nice to be able to get rid of a hacky fix. Thanks for taking the time to look into it.