Unsolved Controller-Worker thread qml signal repeating
-
Hello,
My application communicates to an USB device by custom protocol. I'm moving blocking methods to another thread. And it looks something like this:cpp side: #include <QObject> #include <QThread> #include <QDebug> class Worker : public QObject { Q_OBJECT public: explicit Worker(QObject *parent = nullptr) : QObject(parent) {} signals: void blockingFunction1Finished(); public slots: void blockingFunction1() { qDebug() << "blocking function1 started"; QThread::sleep(1); emit blockingFunction1Finished(); } }; class Controller : public QObject { Q_OBJECT public: explicit Controller(QObject *parent = nullptr) : QObject(parent) { Worker *worker = new Worker; worker->moveToThread(&mWorkerThread); connect(this, &Controller::beginBlockingFunction1, worker, &Worker::blockingFunction1); connect(worker, &Worker::blockingFunction1Finished, this, &Controller::blockingFunction1Finished); mWorkerThread.start(); } Q_INVOKABLE void startBlockingFunction1() { emit beginBlockingFunction1(); } signals: void beginBlockingFunction1(); void blockingFunction1Finished(); public slots: private: QThread mWorkerThread; };
register: qmlRegisterType<Controller>("Qt.Test", 1, 0, "Controller");
qml side: import Qt.Test 1.0 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") Controller { id: controller onBlockingFunction1Finished: console.log("blocking function1 finished") } Button { onClicked: controller.startBlockingFunction1() } }
What bugs me is that I have to? make 2 connections to know that blocking method finished. One connection on cpp side from Worker to Controller and one in qml side.
Is there a way to get around connecting Worker signal to Controller
connect(worker, &Worker::blockingFunction1Finished, this, &Controller::blockingFunction1Finished);
and just have one connection in qmlonBlockingFunction1Finished: console.log("blocking function1 finished")
.And lastly I believe that there is no elegant way to call Worker slot from qml without making a connection and writing a wrapper method to emit a signal:
Q_INVOKABLE void startBlockingFunction1() { emit beginBlockingFunction1(); }
is this correct?
-
hi, there are a couple of things you can do, that I know of, to make your life a bit easier.
first of, no need to wrap your signal in function to call it from qml. The Q_INVOKABLE macro also works directly for signals. Signals are (basically) just functions.
AFAIK you can no simply access a signal in qml, that is emitted from a different Thread in a c++ backend.
But you should be able to chain-connect one signal to another, that reduces the issue to one line of code
-
@J.Hilk Thanks for your feedback.
Could you give me an example how would chain-connecting one signal to another would look like. Or what should I add to my example code to fix the issue? -
@Eligijus said in Controller-Worker thread qml signal repeating:
@J.Hilk Thanks for your feedback.
Could you give me an example how would chain-connecting one signal to another would look like. Or what should I add to my example code to fix the issue?looking through your example, I think you're already doing that. this
connect(worker, &Worker::blockingFunction1Finished, this, &Controller::blockingFunction1Finished);
connects the signal from your worker to the signal of your controller.
-
This post is deleted!