Megidd
Megidd

Reputation: 7959

Progress bar implementation in QML to show progress of a loop in C++

I have my QML UI alongside my C++ code. My loop which I need to show its progress is developed in C++ like this:

for(unsigned int j = 0; j < Count; ++j) {
    // Do stuff
}

On my QML code, I need to progress bar like this:

ProgressBar {
    value: j  // Should come from C++ loop
              // It is "j" on C++ loop
    from: 0   // C++ loop starts out with 0
    to: Count // C++ loop ends with "Count"
}

I don't know how my C++ loop and my QML progress bar need to be linked to each other. I couldn't find any relevant example. Can anybody give me a hint.


The communication between my C++ and QML is done by using Q_PROPERTY like this, but I'm not sure how to use it:

Q_PROPERTY(float j READ j WRITE setJ NOTIFY jChanged)

Upvotes: 1

Views: 4370

Answers (1)

frogatto
frogatto

Reputation: 29285

It's easy! let's go step by step.

  1. Your C++ class should extend QObject and use Q_OBJECT macro inside. I call it Worker for example.

    class Worker : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(float progress READ progress NOTIFY progressChanged)
    public:
        Q_INVOKABLE void start() {
            // start the worker thread in which your loop spins
        }
        float progress(); // progress getter
    signals:
        void progressChanged(float progress);
    };
    
  2. Start a background thread and define its own progressChanged signal.

    for(unsigned int j = 0; j < Count; ++j) {
        // Do stuff
        emit progressChanged(/*current progress*/);
    }
    
  3. Connect background thread's progressChanged to the main thread living object Worker's progressChanged signal (queued connection). This step is required to relay signals from background thread to QML.

  4. Link the C++ class to QML:

    int main(int argc, char *argv[]) {
        QGuiApplication app(argc, argv);
    
        QQuickView view;
        Worker w;
        view.engine()->rootContext()->setContextProperty("worker", &w);
        view.setSource(QUrl::fromLocalFile("MyItem.qml"));
        view.show();
    
        return app.exec();
    }
    
  5. Listen to the signal at QML side:

    ProgressBar {
        id: prg
        from: 0   // C++ loop starts out with 0
        to: Count // C++ loop ends with "Count"
    
        Connections {
            target: worker
            onProgressChanged: prg.value = progress;
        }
    }
    

Upvotes: 3

Related Questions