Reputation: 7959
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
Reputation: 29285
It's easy! let's go step by step.
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);
};
Start a background thread and define its own progressChanged
signal.
for(unsigned int j = 0; j < Count; ++j) {
// Do stuff
emit progressChanged(/*current progress*/);
}
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.
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();
}
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