Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Controller-Worker thread qml signal repeating
Forum Updated to NodeBB v4.3 + New Features

Controller-Worker thread qml signal repeating

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
5 Posts 3 Posters 752 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • E Offline
    E Offline
    Eligijus
    wrote on last edited by Eligijus
    #1

    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 qml onBlockingFunction1Finished: 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?

    J.HilkJ 1 Reply Last reply
    0
    • E Eligijus

      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 qml onBlockingFunction1Finished: 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?

      J.HilkJ Offline
      J.HilkJ Offline
      J.Hilk
      Moderators
      wrote on last edited by
      #2

      @Eligijus

      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


      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


      Q: What's that?
      A: It's blue light.
      Q: What does it do?
      A: It turns blue.

      E 1 Reply Last reply
      0
      • J.HilkJ J.Hilk

        @Eligijus

        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

        E Offline
        E Offline
        Eligijus
        wrote on last edited by
        #3

        @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?

        J.HilkJ 1 Reply Last reply
        0
        • E Eligijus

          @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?

          J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by
          #4

          @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.


          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          1 Reply Last reply
          0
          • K Offline
            K Offline
            kkettinger
            wrote on last edited by kkettinger
            #5
            This post is deleted!
            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved