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. How to return a value from one slot to another

How to return a value from one slot to another

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 3 Posters 1.6k Views
  • 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.
  • S Offline
    S Offline
    sigmind
    wrote on last edited by sigmind
    #1

    I am facing a strange problem. I have successfully tested a threaded program running parallely. However, I wanted to add another thread within that thread like this:

    worker.cpp

    
    #include "worker.h"
    #include <QTimer>
    #include <QEventLoop>
    
    #include <QThread>
    #include <QDebug>
    #include <QUrl>
    #include <QNetworkRequest>
    #include <QNetworkReply>
    #include <QNetworkAccessManager>
    #include <QNetworkReply>
    #include <QNetworkRequest>
    #include <QJsonArray>
    #include <QJsonDocument>
    #include <QJsonObject>
    #include <QJsonValue>
    #include <QJsonValueRef>
    
    Worker::Worker(QObject *parent) :
        QObject(parent)
    {
        _working =false;
        _abort = false;
    }
    
    void Worker::requestWork()
    {
        mutex.lock();
        _working = true;
        _abort = false;
        qDebug()<<"Request worker start in Thread "<<thread()->currentThreadId();
        mutex.unlock();
    
        emit workRequested();
    }
    
    void Worker::abort()
    {
        mutex.lock();
        if (_working) {
            _abort = true;
            qDebug()<<"Request worker aborting in Thread "<<thread()->currentThreadId();
        }
        mutex.unlock();
    }
    
    void Worker::syncRequestFinished(QNetworkReply *rep){
        mutex.lock();
         bool abort = _abort;
         mutex.unlock();
        QString answer = rep->readAll();
    
        qDebug() << answer;
        
        emit valueChanged(pic, str,indx);
        mutex.lock();
        _working = false;
        mutex.unlock();
        emit finishedLPR();
    }
        
        
    void Worker::doWork(QPixmap pic, QString str, int indx)
    {
        qDebug()<<"Starting worker process in Thread "<<thread()->currentThreadId();
    
    
            QString extract = "External API call";
            
            
            QUrl url("https://vision.googleapis.com/v1/images:annotate?key=AIzaSyfbdf************PWDC7qcprU");
    
    
            QNetworkAccessManager *APImanager = new QNetworkAccessManager(this);
                QNetworkRequest Request(url);
    
                Request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
                  Request.setRawHeader("charset", "utf-8");
    
                  connect(APImanager, SIGNAL(finished(QNetworkReply*)),this,
                                        SLOT(syncRequestFinished(QNetworkReply*)));
          
            
                    APImanager->post(Request,json_bytes);
    
        // Set _working to false, meaning the process can't be aborted anymore.
        mutex.lock();
        _working = false;
        mutex.unlock();
    
        qDebug()<<"Worker process finished in Thread "<<thread()->currentThreadId();
    
       
      
    }
    
    

    and worker.h

    
    #ifndef WORKER_H
    #define WORKER_H
    
    #include <QObject>
    #include <QMutex>
    #include <QWidget>
    #include <QUrl>
    #include <QNetworkRequest>
    #include <QNetworkReply>
    
    class Worker : public QObject
    {
        Q_OBJECT
    
    public:
        explicit Worker(QObject *parent = 0);
        /**
         * @brief Requests the process to start
         *
         * It is thread safe as it uses #mutex to protect access to #_working variable.
         */
        void requestWork();
        /**
         * @brief Requests the process to abort
         *
         * It is thread safe as it uses #mutex to protect access to #_abort variable.
         */
        void abort();
    
    private:
        /**
         * @brief Process is aborted when @em true
         */
        bool _abort;
        /**
         * @brief @em true when Worker is doing work
         */
        bool _working;
        /**
         * @brief Protects access to #_abort
         */
        QMutex mutex;
    
        QString plateNum;
    
    signals:
        /**
         * @brief This signal is emitted when the Worker request to Work
         * @sa requestWork()
         */
        void workRequested();
        /**
         * @brief This signal is emitted when counted value is changed (every sec)
         */
        void valueChanged(QPixmap pic, QString str, int indx);
        /**
         * @brief This signal is emitted when process is finished (either by counting 60 sec or being aborted)
         */
        void finished(QNetworkReply*rep);
    
        void finishedLPR();
       
    
    public slots:
    
        void doWork(QPixmap picture, QString str, int indx);
      
    
        void syncRequestFinished(QNetworkReply*rep, QPixmap pic, QString str, int indx);
      
       
    };
    
    #endif // WORKER_H
    
    

    The problem I am facing here is that when the

    emit valueChanged(pic, str,indx)
    
    emit finishedLPR()
    

    signal is being called from

    doWork
    

    slot, its running normally. But as I have network reply dependency, I have to call it from

    syncRequestFinished(QNetworkReply*rep, QPixmap pic, QString str, int indx)
    

    slot which results empty output. Can someone tell me what I am doing wrong? Or how can I pass a value from

    syncRequestFinished()
    

    to

    doWork()
    

    efficiently? Thanks in advance.

    K 1 Reply Last reply
    0
    • S sigmind

      I am facing a strange problem. I have successfully tested a threaded program running parallely. However, I wanted to add another thread within that thread like this:

      worker.cpp

      
      #include "worker.h"
      #include <QTimer>
      #include <QEventLoop>
      
      #include <QThread>
      #include <QDebug>
      #include <QUrl>
      #include <QNetworkRequest>
      #include <QNetworkReply>
      #include <QNetworkAccessManager>
      #include <QNetworkReply>
      #include <QNetworkRequest>
      #include <QJsonArray>
      #include <QJsonDocument>
      #include <QJsonObject>
      #include <QJsonValue>
      #include <QJsonValueRef>
      
      Worker::Worker(QObject *parent) :
          QObject(parent)
      {
          _working =false;
          _abort = false;
      }
      
      void Worker::requestWork()
      {
          mutex.lock();
          _working = true;
          _abort = false;
          qDebug()<<"Request worker start in Thread "<<thread()->currentThreadId();
          mutex.unlock();
      
          emit workRequested();
      }
      
      void Worker::abort()
      {
          mutex.lock();
          if (_working) {
              _abort = true;
              qDebug()<<"Request worker aborting in Thread "<<thread()->currentThreadId();
          }
          mutex.unlock();
      }
      
      void Worker::syncRequestFinished(QNetworkReply *rep){
          mutex.lock();
           bool abort = _abort;
           mutex.unlock();
          QString answer = rep->readAll();
      
          qDebug() << answer;
          
          emit valueChanged(pic, str,indx);
          mutex.lock();
          _working = false;
          mutex.unlock();
          emit finishedLPR();
      }
          
          
      void Worker::doWork(QPixmap pic, QString str, int indx)
      {
          qDebug()<<"Starting worker process in Thread "<<thread()->currentThreadId();
      
      
              QString extract = "External API call";
              
              
              QUrl url("https://vision.googleapis.com/v1/images:annotate?key=AIzaSyfbdf************PWDC7qcprU");
      
      
              QNetworkAccessManager *APImanager = new QNetworkAccessManager(this);
                  QNetworkRequest Request(url);
      
                  Request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
                    Request.setRawHeader("charset", "utf-8");
      
                    connect(APImanager, SIGNAL(finished(QNetworkReply*)),this,
                                          SLOT(syncRequestFinished(QNetworkReply*)));
            
              
                      APImanager->post(Request,json_bytes);
      
          // Set _working to false, meaning the process can't be aborted anymore.
          mutex.lock();
          _working = false;
          mutex.unlock();
      
          qDebug()<<"Worker process finished in Thread "<<thread()->currentThreadId();
      
         
        
      }
      
      

      and worker.h

      
      #ifndef WORKER_H
      #define WORKER_H
      
      #include <QObject>
      #include <QMutex>
      #include <QWidget>
      #include <QUrl>
      #include <QNetworkRequest>
      #include <QNetworkReply>
      
      class Worker : public QObject
      {
          Q_OBJECT
      
      public:
          explicit Worker(QObject *parent = 0);
          /**
           * @brief Requests the process to start
           *
           * It is thread safe as it uses #mutex to protect access to #_working variable.
           */
          void requestWork();
          /**
           * @brief Requests the process to abort
           *
           * It is thread safe as it uses #mutex to protect access to #_abort variable.
           */
          void abort();
      
      private:
          /**
           * @brief Process is aborted when @em true
           */
          bool _abort;
          /**
           * @brief @em true when Worker is doing work
           */
          bool _working;
          /**
           * @brief Protects access to #_abort
           */
          QMutex mutex;
      
          QString plateNum;
      
      signals:
          /**
           * @brief This signal is emitted when the Worker request to Work
           * @sa requestWork()
           */
          void workRequested();
          /**
           * @brief This signal is emitted when counted value is changed (every sec)
           */
          void valueChanged(QPixmap pic, QString str, int indx);
          /**
           * @brief This signal is emitted when process is finished (either by counting 60 sec or being aborted)
           */
          void finished(QNetworkReply*rep);
      
          void finishedLPR();
         
      
      public slots:
      
          void doWork(QPixmap picture, QString str, int indx);
        
      
          void syncRequestFinished(QNetworkReply*rep, QPixmap pic, QString str, int indx);
        
         
      };
      
      #endif // WORKER_H
      
      

      The problem I am facing here is that when the

      emit valueChanged(pic, str,indx)
      
      emit finishedLPR()
      

      signal is being called from

      doWork
      

      slot, its running normally. But as I have network reply dependency, I have to call it from

      syncRequestFinished(QNetworkReply*rep, QPixmap pic, QString str, int indx)
      

      slot which results empty output. Can someone tell me what I am doing wrong? Or how can I pass a value from

      syncRequestFinished()
      

      to

      doWork()
      

      efficiently? Thanks in advance.

      K Offline
      K Offline
      koahnig
      wrote on last edited by koahnig
      #2

      @sigmind said in How to return a value from one slot to another:

          QNetworkAccessManager *APImanager = new QNetworkAccessManager(this);
          QNetworkRequest Request(url);
      
          Request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
          Request.setRawHeader("charset", "utf-8");
      
          connect(APImanager, SIGNAL(finished(QNetworkReply*, QPixmap, QString, int)),this,
                                      SLOT(syncRequestFinished(QNetworkReply*, QPixmap, QString, int)));
      

      This is copied from your worker.cpp
      Check the return value of the connect and also the application output. That cannot work.

      QNetworkAccessManager *APImanager = new QNetworkAccessManager(this); // that is a standard Qt class
       
      connect(APImanager, SIGNAL(finished(QNetworkReply*, QPixmap, QString, int)),this,
                                           SLOT(syncRequestFinished(QNetworkReply*, QPixmap, QString, int))); // it has no signal finished with that parameter list
      

      See here

      I have seen a signal defined in worker.h which has that parameter list. However, how should the standard class QNetworkAccessManager know this signal and even have an idea what to assign.

      The signal you define in worker.h will be a signal you can emit from routines of worker.cpp.

      IMHO it is easier to use the functor-based connect, that will tell you immediately that you have done something at this point.

      Vote the answer(s) that helped you to solve your issue(s)

      1 Reply Last reply
      0
      • S Offline
        S Offline
        sigmind
        wrote on last edited by sigmind
        #3

        @koahnig
        Ok I understand that. So modifying it to

        connect(APImanager, SIGNAL(finished()),this,
                                     SLOT(syncRequestFinished(QNetworkReply*)));
        

        Now how to return the value from syncRequestfinished slot to the doWork() slot?

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by SGaist
          #4

          Hi,

          The goal of the slots is not to return values. Can you explain exactly what you are trying to achieve ?

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • S Offline
            S Offline
            sigmind
            wrote on last edited by
            #5

            I am trying to emit the signal

            emit valueChanged()
            

            from the

            doWork
            

            slot when the API manager

            syncRequestFinished()
            

            finishes and then return the "replay value" to the

            doWork()
            

            slot synchronously.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Why do you need to be synchronous in that method ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • S Offline
                S Offline
                sigmind
                wrote on last edited by
                #7

                I have tried to emit the signal valueChanged() from syncRequestFinished() slot, but that slot cannot take other parameters except **QNetworkReply *** . Thats why synchronization needed.

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Again, I don't see what part of this requires that your doWork method content be synchronous.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • S Offline
                    S Offline
                    sigmind
                    wrote on last edited by sigmind
                    #9

                    @SGaist @koahnig Slightly updated my original post to make it clear.
                    Okey, briefly, please understand that the doWork(QPixmap pic, QString str, int indx) function takes 3 arguments and emit valueChanged(pic, str,indx) signal also returns 3 arguments. But the problem is, the doWork() slot also contains a Qt Network request, which is connected to syncRequestFinished() slot.

                    Now, I had successfully emitted 3 arguments to the doWork() slot, the doWork() slot then take the QPixmap and call external API to OCR it. When the request finishes, I have to emit the OCR value to valueChange( ) slot along with other parameters found on doWork() slot.

                    I could have easily emit the valueChanged() signal from syncRequestFinished() slot, but it takes default argument, no more no less. So I found no way to emit the valueChanged() signal from there. I have also tried to declare global variable and update from slots, but I found it not synchronous.
                    That is why I wanted to sync it to the doWork() slot. Any suggestion would be highly appreciated.

                    K 1 Reply Last reply
                    0
                    • SGaistS Offline
                      SGaistS Offline
                      SGaist
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      What about simplifying that using a lambda expression where you pass it the complementary parameters you need ? See the new connect syntax.

                      Interested in AI ? www.idiap.ch
                      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                      1 Reply Last reply
                      2
                      • S sigmind

                        @SGaist @koahnig Slightly updated my original post to make it clear.
                        Okey, briefly, please understand that the doWork(QPixmap pic, QString str, int indx) function takes 3 arguments and emit valueChanged(pic, str,indx) signal also returns 3 arguments. But the problem is, the doWork() slot also contains a Qt Network request, which is connected to syncRequestFinished() slot.

                        Now, I had successfully emitted 3 arguments to the doWork() slot, the doWork() slot then take the QPixmap and call external API to OCR it. When the request finishes, I have to emit the OCR value to valueChange( ) slot along with other parameters found on doWork() slot.

                        I could have easily emit the valueChanged() signal from syncRequestFinished() slot, but it takes default argument, no more no less. So I found no way to emit the valueChanged() signal from there. I have also tried to declare global variable and update from slots, but I found it not synchronous.
                        That is why I wanted to sync it to the doWork() slot. Any suggestion would be highly appreciated.

                        K Offline
                        K Offline
                        koahnig
                        wrote on last edited by
                        #11

                        @sigmind

                        Stupid question: Does your code compile as posted?

                        In worker.cpp you have

                        void Worker::syncRequestFinished(QNetworkReply *rep){
                            mutex.lock();
                             bool abort = _abort;
                             mutex.unlock();
                            QString answer = rep->readAll();
                        
                            qDebug() << answer;
                            
                            emit valueChanged(pic, str,indx);
                        
                            mutex.lock();
                            _working = false;
                            mutex.unlock();
                            emit finishedLPR();
                        }
                        

                        The parameters used in emit valueChanged(pic, str,indx) are neither local nor in the definition of the class nor global.

                        Vote the answer(s) that helped you to solve your issue(s)

                        1 Reply Last reply
                        1

                        • Login

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