Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QML call function in C++ with threads
Forum Updated to NodeBB v4.3 + New Features

QML call function in C++ with threads

Scheduled Pinned Locked Moved Unsolved General and Desktop
qthreadsqmlqfutureqinvokableqmlc++
22 Posts 4 Posters 19.2k 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.
  • jsulmJ jsulm

    @JosephMills OK, understand. But the name singleton is somehow misleading.

    J Offline
    J Offline
    JosephMills
    wrote on last edited by
    #6

    @jsulm I hear that lol if you like take a look here
    http://doc.qt.io/qt-5/qqmlengine.html#qmlRegisterSingletonType

    because it is the QObject that is getting returned from the template. Also would not hurt to make total static on the QObject,

    1 Reply Last reply
    0
    • Cleiton BuenoC Offline
      Cleiton BuenoC Offline
      Cleiton Bueno
      wrote on last edited by
      #7

      I'll try to explain better what I need:

      Here is an example code.

      mytask.h and mytask.cpp

      class myTask : public QObject
      {
      Q_OBJECT

      public:
      myTask();

      virtual ~myTask();
      
      Q_INVOKABLE void func1(void) { while(1) { qDebug() << "Running Func1" << endl; QThread::msleep(500); } }
      Q_INVOKABLE void func2(void) { while(1) { qDebug() << "Running Func2" << endl; QThread::msleep(500); } }
      Q_INVOKABLE void func3(void) { while(1) { qDebug() << "Running Func3" << endl; QThread::msleep(500); } }
      

      }

      main.cpp
      ...
      // Register our component type with QML.
      qmlRegisterType<myTask>("com.task", 1, 0, "MyTask");
      ...

      main.qml
      ...
      MyTask {
      id: task
      }

      Rectangle {
         width: 50; height: width;
         color: "red"
         MouseArea {
           anchors.fill: parent
           onClicked: {
             console.log("call function 1 Qt/C++");
             task.func1();
      	 }
         }
      }
      
      Rectangle {
         width: 50; height: width;
         color: "blue"
         MouseArea {
           anchors.fill: parent
           onClicked: {
             console.log("call function 2 Qt/C++");
             task.func2();
      	 }
         }
      }
      

      So I have to "fire" || "perform" functions (func1, func2, func3) as Threads and were running.

      1 Reply Last reply
      0
      • jsulmJ jsulm

        @JosephMills said in QML call function in C++ with threads:

        static QObject *initSingleton(QQmlEngine *engine, QJSEngine *scriptEngine)
        {
        Q_UNUSED(engine)
        Q_UNUSED(scriptEngine)

        MyClass *myClass = new MyClass();
        return myClass;
        

        }

        This is not a singleton as you create a new instance each time this function is called. It should be:

        static QObject *initSingleton(QQmlEngine *engine, QJSEngine *scriptEngine)
        {
            Q_UNUSED(engine)
            Q_UNUSED(scriptEngine)
        
            static MyClass *myClass = new MyClass();
            return myClass;
        }
        
        jeremy_kJ Offline
        jeremy_kJ Offline
        jeremy_k
        wrote on last edited by
        #8

        @jsulm said in QML call function in C++ with threads:

        @JosephMills said in QML call function in C++ with threads:

        static QObject *initSingleton(QQmlEngine *engine, QJSEngine *scriptEngine)
        {
        Q_UNUSED(engine)
        Q_UNUSED(scriptEngine)

        MyClass *myClass = new MyClass();
        return myClass;
        

        }

        This is not a singleton as you create a new instance each time this function is called. It should be:

        static QObject *initSingleton(QQmlEngine *engine, QJSEngine *scriptEngine)
        {
            Q_UNUSED(engine)
            Q_UNUSED(scriptEngine)
        
            static MyClass *myClass = new MyClass();
            return myClass;
        }
        

        It's a singleton with respect to the QML engine, not the process. Each engine will attempt to create its own singletons. Returning the same object to multiple engines might not achieve the desired result.

        Asking a question about code? http://eel.is/iso-c++/testcase/

        1 Reply Last reply
        0
        • Cleiton BuenoC Offline
          Cleiton BuenoC Offline
          Cleiton Bueno
          wrote on last edited by
          #9

          My idea is to call functions implemented in C ++ class but not "freeze" my application QML.

          Calling directly without QThread, my QML freezes!

          So I thought about using QtConcurrent or QThread for functions, I am evaluating.

          jsulmJ 1 Reply Last reply
          0
          • Cleiton BuenoC Cleiton Bueno

            My idea is to call functions implemented in C ++ class but not "freeze" my application QML.

            Calling directly without QThread, my QML freezes!

            So I thought about using QtConcurrent or QThread for functions, I am evaluating.

            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #10

            @Cleiton-Bueno Are your C++ functions doing heavy calculations?

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            Cleiton BuenoC 1 Reply Last reply
            0
            • jsulmJ jsulm

              @Cleiton-Bueno Are your C++ functions doing heavy calculations?

              Cleiton BuenoC Offline
              Cleiton BuenoC Offline
              Cleiton Bueno
              wrote on last edited by
              #11

              @jsulm said in QML call function in C++ with threads:

              Are your C++ functions doing heavy calculations?

              @jsulm No. A function will pooling and perform reading in a pin via SysFS, another function will "tick" on a pin, but are fired at different times and may be performed "together".

              jsulmJ 1 Reply Last reply
              0
              • Cleiton BuenoC Cleiton Bueno

                @jsulm said in QML call function in C++ with threads:

                Are your C++ functions doing heavy calculations?

                @jsulm No. A function will pooling and perform reading in a pin via SysFS, another function will "tick" on a pin, but are fired at different times and may be performed "together".

                jsulmJ Offline
                jsulmJ Offline
                jsulm
                Lifetime Qt Champion
                wrote on last edited by
                #12

                @Cleiton-Bueno Then I don't understand why your UI is freezing. Did you test and saw this freezing or do you just assume it will freeze?

                https://forum.qt.io/topic/113070/qt-code-of-conduct

                Cleiton BuenoC 1 Reply Last reply
                0
                • jsulmJ jsulm

                  @Cleiton-Bueno Then I don't understand why your UI is freezing. Did you test and saw this freezing or do you just assume it will freeze?

                  Cleiton BuenoC Offline
                  Cleiton BuenoC Offline
                  Cleiton Bueno
                  wrote on last edited by
                  #13

                  @jsulm said in QML call function in C++ with threads:

                  Then I don't understand why your UI is freezing. Did you test and saw this freezing or do you just assume it will freeze?

                  @jsulm Because functions are with while (true) {} with 500ms delay, time is undetermined can be short or take a long time, and this function is sending a signal to my GUi QML that already ok.

                  jsulmJ 1 Reply Last reply
                  0
                  • Cleiton BuenoC Cleiton Bueno

                    @jsulm said in QML call function in C++ with threads:

                    Then I don't understand why your UI is freezing. Did you test and saw this freezing or do you just assume it will freeze?

                    @jsulm Because functions are with while (true) {} with 500ms delay, time is undetermined can be short or take a long time, and this function is sending a signal to my GUi QML that already ok.

                    jsulmJ Offline
                    jsulmJ Offline
                    jsulm
                    Lifetime Qt Champion
                    wrote on last edited by
                    #14

                    @Cleiton-Bueno Such loops are usually a sign of bad design. Especially in event based Qt you should avoid them. Why do you want to call a blocking function from QML? You should rethink your design and try to use signals/slots.

                    https://forum.qt.io/topic/113070/qt-code-of-conduct

                    Cleiton BuenoC 1 Reply Last reply
                    0
                    • jsulmJ jsulm

                      @Cleiton-Bueno Such loops are usually a sign of bad design. Especially in event based Qt you should avoid them. Why do you want to call a blocking function from QML? You should rethink your design and try to use signals/slots.

                      Cleiton BuenoC Offline
                      Cleiton BuenoC Offline
                      Cleiton Bueno
                      wrote on last edited by
                      #15

                      @jsulm This was an example!
                      I have no functions while (1), but have functions that when called will process for a while, for example, have a function that when activated will be communicating via I2C and the function returns me status of the Motor, until it stops.

                      When I do that my QML GUI hangs as solve this with signals/slots? It would be helpful, used signals/slots but not in this case.
                      So I thought about using QThread within the function

                      jsulmJ 1 Reply Last reply
                      0
                      • Cleiton BuenoC Cleiton Bueno

                        @jsulm This was an example!
                        I have no functions while (1), but have functions that when called will process for a while, for example, have a function that when activated will be communicating via I2C and the function returns me status of the Motor, until it stops.

                        When I do that my QML GUI hangs as solve this with signals/slots? It would be helpful, used signals/slots but not in this case.
                        So I thought about using QThread within the function

                        jsulmJ Offline
                        jsulmJ Offline
                        jsulm
                        Lifetime Qt Champion
                        wrote on last edited by
                        #16

                        @Cleiton-Bueno If you don't want to block the UI you need asynchronous communication, even with a thread. That's why I suggested to use signals/slots. For example from the UI you could call a C++ function which triggers an action and returns immediately. As soon as the result is available your C++ code emits a signal with results which is connected to your UI.
                        If I understood you correctly you're already using a thread but your UI is still blocking, right? How do you use that thread? You should show some code.

                        https://forum.qt.io/topic/113070/qt-code-of-conduct

                        1 Reply Last reply
                        0
                        • Cleiton BuenoC Offline
                          Cleiton BuenoC Offline
                          Cleiton Bueno
                          wrote on last edited by
                          #17

                          Sorry about the delay @jsulm.
                          I removed some parts of the code by NDA but I'm trying to expose the idea.

                          mytask.h

                          #ifndef MYTASK_H
                          #define MYTASK_H
                          
                          #include <QObject>
                          #include <QTcpSocket>
                          #include <QTimer>
                          #include <QDebug>
                          
                          #include <QThread>
                          
                          class task : public QObject
                          {
                              Q_OBJECT
                              Q_PROPERTY(QString msg READ msg WRITE setMsg NOTIFY msgChanged )
                          	...
                          
                          public:
                              task();
                          
                              virtual ~task();
                          
                              Q_INVOKABLE void runGetMotor(void);
                              ...
                          
                              QString err;
                          
                          private:
                              QTcpSocket *socket;
                          	...
                          
                          
                          private slots:
                              void onSocketReadData();
                              void onSocketConnected();
                              void onSocketDisconnected();
                              void onSocketError(QAbstractSocket::SocketError);
                          
                          signals:
                              void progressMotor(int progress);
                          	...
                          };
                          
                          #endif // MYTASK_H
                          
                          

                          mytask.cpp

                          //your code here
                          #include "mytask.h"
                          
                          
                          /**
                           * @brief mytask::mytask
                           *  Metodo construtor e inicialização de variaveis e objetos privados da classe task
                           */
                          mytask::mytask()
                          {
                              if (DEBUG_TASK)
                                  qDebug() << "Init class and socket";
                          
                              /* create socket */
                              socket = new QTcpSocket(this);
                          
                              if(DEBUG_TASK)
                                  qDebug() << "Connecting signal <-> slots";
                          
                              connect(socket, SIGNAL(readyRead()), this, SLOT(onSocketReadData()));
                              connect(socket, SIGNAL(connected()), this, SLOT(onSocketConnected()));
                              connect(socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
                              connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onSocketError(QAbstractSocket::SocketError)));
                          
                          
                          }
                          
                          
                          /**
                           * @brief mytask::~mytask
                           *  Metodo destrutivo da classe mytask
                           */
                          mytask::~mytask()
                          {
                              socket->close();
                              delete socket;
                          }
                          
                          
                          void mytask::runGoMotor(void)
                          {
                            ...
                            this->runProgress();
                            ...
                          }
                          
                          
                          void mytask::runProgress(void)
                          {
                          	/* Here I need to shoot this routine as Thread */
                          	int returnLoop=255;
                          	while(returnLoop) {
                          		/* Here send/get command, process and emit signal send data to QML */
                          		emit progressMotor(/* HERE VARIABLE WITH VALUE PROCESSED */);
                                                  // Update value returnLoop or break loop
                                          QThread::sleep(1);
                              }
                          
                          }
                          
                          

                          main.cpp

                              ...
                              // Register our component type with QML.
                              qmlRegisterType<mytask>("com.sys.motor", 1, 0, "MyTask");
                              ...
                          

                          main.qml

                              MyTask {
                                  id: task
                          
                              }
                          
                          	Rectangle {
                          		...
                          		onClicked: {
                                     task.runGoMotor();
                                  }
                              }
                          	
                          
                          
                          
                              Connections {
                                  target: task
                          
                                  onProgressMotor: {
                                      console.log("Progress Motor: "+progress);
                          			//Set variable to show value
                                  }
                          
                              }
                          

                          There are other checks and conditions to enter the while (), and at one point for the loop.

                          I'm auditioning QTimer starting in the constructor and it seems that met the need, something like:

                          MyTask::MyTask(QObject *parent) : QObject(parent)
                          {
                              timer = new QTimer(this);
                              timer->setInterval(1000);
                              connect(timer, SIGNAL(timeout()), this, SLOT(setProgressMotor()));
                          }
                          

                          The routine would be:

                          Click GUi QML button -> Function C ++ (runGoMotor ()), check some conditions and calls (runProgress ()), and in turn will send commands to the Socket and process the response, so to get something to close the loop.

                          jsulmJ 1 Reply Last reply
                          0
                          • Cleiton BuenoC Cleiton Bueno

                            Sorry about the delay @jsulm.
                            I removed some parts of the code by NDA but I'm trying to expose the idea.

                            mytask.h

                            #ifndef MYTASK_H
                            #define MYTASK_H
                            
                            #include <QObject>
                            #include <QTcpSocket>
                            #include <QTimer>
                            #include <QDebug>
                            
                            #include <QThread>
                            
                            class task : public QObject
                            {
                                Q_OBJECT
                                Q_PROPERTY(QString msg READ msg WRITE setMsg NOTIFY msgChanged )
                            	...
                            
                            public:
                                task();
                            
                                virtual ~task();
                            
                                Q_INVOKABLE void runGetMotor(void);
                                ...
                            
                                QString err;
                            
                            private:
                                QTcpSocket *socket;
                            	...
                            
                            
                            private slots:
                                void onSocketReadData();
                                void onSocketConnected();
                                void onSocketDisconnected();
                                void onSocketError(QAbstractSocket::SocketError);
                            
                            signals:
                                void progressMotor(int progress);
                            	...
                            };
                            
                            #endif // MYTASK_H
                            
                            

                            mytask.cpp

                            //your code here
                            #include "mytask.h"
                            
                            
                            /**
                             * @brief mytask::mytask
                             *  Metodo construtor e inicialização de variaveis e objetos privados da classe task
                             */
                            mytask::mytask()
                            {
                                if (DEBUG_TASK)
                                    qDebug() << "Init class and socket";
                            
                                /* create socket */
                                socket = new QTcpSocket(this);
                            
                                if(DEBUG_TASK)
                                    qDebug() << "Connecting signal <-> slots";
                            
                                connect(socket, SIGNAL(readyRead()), this, SLOT(onSocketReadData()));
                                connect(socket, SIGNAL(connected()), this, SLOT(onSocketConnected()));
                                connect(socket, SIGNAL(disconnected()), this, SLOT(onSocketDisconnected()));
                                connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onSocketError(QAbstractSocket::SocketError)));
                            
                            
                            }
                            
                            
                            /**
                             * @brief mytask::~mytask
                             *  Metodo destrutivo da classe mytask
                             */
                            mytask::~mytask()
                            {
                                socket->close();
                                delete socket;
                            }
                            
                            
                            void mytask::runGoMotor(void)
                            {
                              ...
                              this->runProgress();
                              ...
                            }
                            
                            
                            void mytask::runProgress(void)
                            {
                            	/* Here I need to shoot this routine as Thread */
                            	int returnLoop=255;
                            	while(returnLoop) {
                            		/* Here send/get command, process and emit signal send data to QML */
                            		emit progressMotor(/* HERE VARIABLE WITH VALUE PROCESSED */);
                                                    // Update value returnLoop or break loop
                                            QThread::sleep(1);
                                }
                            
                            }
                            
                            

                            main.cpp

                                ...
                                // Register our component type with QML.
                                qmlRegisterType<mytask>("com.sys.motor", 1, 0, "MyTask");
                                ...
                            

                            main.qml

                                MyTask {
                                    id: task
                            
                                }
                            
                            	Rectangle {
                            		...
                            		onClicked: {
                                       task.runGoMotor();
                                    }
                                }
                            	
                            
                            
                            
                                Connections {
                                    target: task
                            
                                    onProgressMotor: {
                                        console.log("Progress Motor: "+progress);
                            			//Set variable to show value
                                    }
                            
                                }
                            

                            There are other checks and conditions to enter the while (), and at one point for the loop.

                            I'm auditioning QTimer starting in the constructor and it seems that met the need, something like:

                            MyTask::MyTask(QObject *parent) : QObject(parent)
                            {
                                timer = new QTimer(this);
                                timer->setInterval(1000);
                                connect(timer, SIGNAL(timeout()), this, SLOT(setProgressMotor()));
                            }
                            

                            The routine would be:

                            Click GUi QML button -> Function C ++ (runGoMotor ()), check some conditions and calls (runProgress ()), and in turn will send commands to the Socket and process the response, so to get something to close the loop.

                            jsulmJ Offline
                            jsulmJ Offline
                            jsulm
                            Lifetime Qt Champion
                            wrote on last edited by
                            #18

                            @Cleiton-Bueno said in QML call function in C++ with threads:

                            while(returnLoop) {
                            /* Here send/get command, process and emit signal send data to QML /
                            emit progressMotor(/
                            HERE VARIABLE WITH VALUE PROCESSED */);
                            // Update value returnLoop or break loop
                            QThread::sleep(1);
                            }

                            This while loop blocks the Qt event loop in your thread. That means: the signal will not be emitted until the loop is finished! You either should call http://doc.qt.io/qt-5/qcoreapplication.html#processEvents in the loop or, even better, get rid of this loop.

                            https://forum.qt.io/topic/113070/qt-code-of-conduct

                            jeremy_kJ 1 Reply Last reply
                            0
                            • jsulmJ jsulm

                              @Cleiton-Bueno said in QML call function in C++ with threads:

                              while(returnLoop) {
                              /* Here send/get command, process and emit signal send data to QML /
                              emit progressMotor(/
                              HERE VARIABLE WITH VALUE PROCESSED */);
                              // Update value returnLoop or break loop
                              QThread::sleep(1);
                              }

                              This while loop blocks the Qt event loop in your thread. That means: the signal will not be emitted until the loop is finished! You either should call http://doc.qt.io/qt-5/qcoreapplication.html#processEvents in the loop or, even better, get rid of this loop.

                              jeremy_kJ Offline
                              jeremy_kJ Offline
                              jeremy_k
                              wrote on last edited by
                              #19

                              @jsulm said in QML call function in C++ with threads:

                              @Cleiton-Bueno said in QML call function in C++ with threads:

                              while(returnLoop) {
                              /* Here send/get command, process and emit signal send data to QML /
                              emit progressMotor(/
                              HERE VARIABLE WITH VALUE PROCESSED */);
                              // Update value returnLoop or break loop
                              QThread::sleep(1);
                              }

                              This while loop blocks the Qt event loop in your thread. That means: the signal will not be emitted until the loop is finished!

                              Signals, which are a direct function call of moc-generated code, will be emitted. Events won't be processed in the thread, which means that queued connection slots in the same thread won't be called.

                              I agree that the forever { emit && sleep } construct is troubling.

                              Asking a question about code? http://eel.is/iso-c++/testcase/

                              jsulmJ 1 Reply Last reply
                              0
                              • jeremy_kJ jeremy_k

                                @jsulm said in QML call function in C++ with threads:

                                @Cleiton-Bueno said in QML call function in C++ with threads:

                                while(returnLoop) {
                                /* Here send/get command, process and emit signal send data to QML /
                                emit progressMotor(/
                                HERE VARIABLE WITH VALUE PROCESSED */);
                                // Update value returnLoop or break loop
                                QThread::sleep(1);
                                }

                                This while loop blocks the Qt event loop in your thread. That means: the signal will not be emitted until the loop is finished!

                                Signals, which are a direct function call of moc-generated code, will be emitted. Events won't be processed in the thread, which means that queued connection slots in the same thread won't be called.

                                I agree that the forever { emit && sleep } construct is troubling.

                                jsulmJ Offline
                                jsulmJ Offline
                                jsulm
                                Lifetime Qt Champion
                                wrote on last edited by
                                #20

                                @jeremy_k I don't think the signals will be emitted. Signal/slots connections between two threads are not direct connections but queued connections.

                                https://forum.qt.io/topic/113070/qt-code-of-conduct

                                jeremy_kJ 1 Reply Last reply
                                0
                                • jsulmJ jsulm

                                  @jeremy_k I don't think the signals will be emitted. Signal/slots connections between two threads are not direct connections but queued connections.

                                  jeremy_kJ Offline
                                  jeremy_kJ Offline
                                  jeremy_k
                                  wrote on last edited by
                                  #21

                                  @jsulm Pulling code from moc output I happen to have lying around:

                                  For a signal void stuffChanged(QString), moc generates:

                                  // SIGNAL 0
                                  void Singleton::stuffChanged(QString _t1)
                                  {
                                      void *_a[] = { Q_NULLPTR, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
                                      QMetaObject::activate(this, &staticMetaObject, 0, _a);
                                  }
                                  

                                  QMetaObject::activate() is a private API in qtbase/src/corelib/kernel/qobject.cpp. The version that takes a pointer to the static meta object eventually calls this one:

                                  void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_index, void **argv)
                                  {
                                   ...
                                          if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
                                                  || (c->connectionType == Qt::QueuedConnection)) {
                                                  queued_activate(sender, signal_index, c, argv ? argv : empty_argv, locker);
                                                  continue;
                                  ...
                                  }
                                  

                                  The full source is a little lengthy to quote here, but check it out if you're curious. Also, you can trace the emission of a signal through to the call of a slot for an object in the same thread without a return to the event loop with the debugger.

                                  To reiterate, signal emission is done when emit signal() returns. Calling of a particular slot may be pending for any queued connection.

                                  Asking a question about code? http://eel.is/iso-c++/testcase/

                                  1 Reply Last reply
                                  0
                                  • Cleiton BuenoC Offline
                                    Cleiton BuenoC Offline
                                    Cleiton Bueno
                                    wrote on last edited by
                                    #22

                                    I agree, this while() was bothering me.

                                    I'm using a _timer with QTimer where start() by clicking, I get the Socket data with onReadyRead() process met _timer.stop() but emito sign for the status, seems to be working well.

                                    But I accept suggestions for improvement, but I removed the loop while()

                                    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