Why is my progress bar updating...?

My main goal is to understand how my background thread can update the UI over time and read/write state in MyEditor.

I define a progress bar in my MyEditor.h:

class MyEditor  : public juce::AudioProcessorEditor, public juce::FileDragAndDropTarget
{
// ... lot of code skipped here
private:
    // UI progress bar 
    std::unique_ptr<juce::ProgressBar> progressBar;
    
    // our thread for loading files and updating progress bar
    class MeterThread : public juce::Thread {
        public:
        juce::String filepath;
        double progress = 0.0;
        MeterThread() : juce::Thread("Meter Thread") { }
        
        void run() override {            
            for (int i = 0; i < 10; i++) {
                // ... lots of processing here ...
                progress += 0.1;
            }
        }
        
        void setFilepath(juce::String& path) {
            this->filepath = path;
        }        
    };
};

and then in MyEditor.cpp I both set up the progress bar, and then run it when a user drag and drops an audio file:

void MyEditor::setupProgressBar() {
    progressBar = std::make_unique<juce::ProgressBar>(meterThread.progress);
    this->addChildComponent(progressBar.get());
}

// ... lots of code skipped here, obviously

void MyEditor::filesDropped (const juce::StringArray &files, int x, int y) {
      meterThread.setFilepath(files[0]);
      meterThread.progress = 0.0;
      meterThread.startThread();
}

So basically what I’m doing is attaching the UI’s progress bar to the thread’s progress double variable. This double variable gets updated in the loop, but nowhere do I tell the progress bar to fetch this value? So unless the progress bar constructor std::make_unique<juce::ProgressBar>(meterThread.progress) hands in the pointer to meterThread.progress, I don’t see how the progress bar would know to update?

I am just learning JUCE and fairly bad with C++, so this might be an easy thing I’m missing. Asking to learn!

The ProgressBar constructor takes and stores a reference (effectively the same as a pointer) to the double variable and redraws itself periodically with a timer callback. So it “magically” appears the progress bar updates itself when you just change the original double variable.

1 Like

do most other UI components do this? is this a good pattern for having them update?

No, the ProgressBar is not a great example of how to do things. It for example doesn’t use an atomic variable for the progress amount, which is technically wrong when multiple threads are involved. It also does that timer based “polling” of the value, which is a bit wasteful way to do things. (But it can sometimes be the easiest/most straightforward solution to get GUI things to update.)

1 Like

I see. So in general for JUCE, what is the best way to have a thread update UI elements on the editor?

ie: a string on a label, set a variable on another element, etc

Few different ways - but the check should be an atomic one, or a fifo with an atomic index check. In terms of updating you can use a VBlankAttachment to do the check, if it needs updating, do it from there and call a repaint or update the label etc.