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. Weird issue with SIGNAL/SLOT
Forum Updated to NodeBB v4.3 + New Features

Weird issue with SIGNAL/SLOT

Scheduled Pinned Locked Moved Solved General and Desktop
12 Posts 3 Posters 883 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.
  • L Offline
    L Offline
    leinad
    wrote on last edited by leinad
    #1

    Hi,
    I've been using signal and slots mostly between processes running under multiple threads but now I'm try instantiate two classes under a signal thread and using signal/slot to communicate between them. But for some reason the slot from one object is not being received from the other. Here is an example.

    I'm creating a thread in a class:

    #include "PluginWorker.h"
    
    void StartThread::startThread()
    {
        std::cout << "STARTING THREAD" << std::endl;
    
        QThread* pluginWorkerThread = new QThread;
        pluginWorkerThread->setObjectName("pluginWorkerThread");
        PluginWorker *pluginWorker = new PluginWorker;
        pluginWorker->moveToThread(pluginWorkerThread);
        
        connect(pluginWorker, SIGNAL(finished()), pluginWorkerThread, SLOT(quit()));
        connect(pluginWorker, SIGNAL(finished()), pluginWorker, SLOT(deleteLater()));
        connect(pluginWorkerThread, SIGNAL(finished()), pluginWorkerThread, SLOT(deleteLater()));
        connect(this, SIGNAL(sendExit()), pluginWorker, SLOT(receiveExit()), Qt::DirectConnection);
    
        pluginWorkerThread->start();
    }
    

    Once the thread is started using this call from another class

    startThread_ = new StartThread();
    startThread_->startThread();
    

    The thread does indeed start so far it is ok.
    In the pluginWorker class which runs under the above thread, I instantiate 2 classes as follows:

    PluginWorker::PluginWorker() :
       selectdatabase_(nullptr)
      ,databaseProcessing_(nullptr)
    {
        std::cout << "STARTING PLUGIN WORKER" << std::endl;
    
        databaseProcessing_ = new DatabaseProcessing(); 
        selectdatabase_ = new SelectDatabase();
    
        //setup communication between selectdatabase_ and databaseProcessing_
        connect(selectdatabase_, SIGNAL(sendDatabaseName(QString)), databaseProcessing_, SLOT(getDatabaseName(QString)));
    
    }
    

    However when I emit from selectDatabase::sendDatabaseName to the slot in databaseProcessing::getDatabaseName nothing is received.

    I'm using Q_Object in both classes for selectDatabase_ and databaseProcessing_

    Below is a include example, both are similar:

    #ifndef DATBASEPROCESSING_H
    #define DATBASEPROCESSING_H
    
    #include <QObject>
    #include <QMainWindow>
    
    class DatabaseProcessing : public QObject
    {
        Q_OBJECT
    
    public:
        DatabaseProcessing();
        virtual ~DatabaseProcessing();
    
    
    public Q_SLOTS:
        void getDatabaseName(QString databaseName);
    };
    

    Would anyone have any idea why the slot is not being called? I really would appreciate any feedback.

    Thanks!

    JonBJ 1 Reply Last reply
    0
    • JonBJ JonB

      @leinad
      This was just the first step. Now we know the signal does get emitted and the connect() attaches to it.

      Now:

      connect(selectdatabase_, &SelectDatabase::sendDatabaseName, databaseProcessing_, &DatabaseProcessing::getDatabaseName)
      

      (Put a qDebug() << databaseName; as first statement in slot.) I presume you will say the slot does not get called?

      If not, are selectdatabase_ and databaseProcessing_ in different threads? If so, do you allow the event loop to run (signals across threads are queued)?

      L Offline
      L Offline
      leinad
      wrote on last edited by
      #12

      @JonB
      I figured out what is happening. Seems the Emit is being called before the connect statement had a chance to be called. I'll have to rearrange how statements get executed.

      Thanks!

      1 Reply Last reply
      0
      • L leinad

        Hi,
        I've been using signal and slots mostly between processes running under multiple threads but now I'm try instantiate two classes under a signal thread and using signal/slot to communicate between them. But for some reason the slot from one object is not being received from the other. Here is an example.

        I'm creating a thread in a class:

        #include "PluginWorker.h"
        
        void StartThread::startThread()
        {
            std::cout << "STARTING THREAD" << std::endl;
        
            QThread* pluginWorkerThread = new QThread;
            pluginWorkerThread->setObjectName("pluginWorkerThread");
            PluginWorker *pluginWorker = new PluginWorker;
            pluginWorker->moveToThread(pluginWorkerThread);
            
            connect(pluginWorker, SIGNAL(finished()), pluginWorkerThread, SLOT(quit()));
            connect(pluginWorker, SIGNAL(finished()), pluginWorker, SLOT(deleteLater()));
            connect(pluginWorkerThread, SIGNAL(finished()), pluginWorkerThread, SLOT(deleteLater()));
            connect(this, SIGNAL(sendExit()), pluginWorker, SLOT(receiveExit()), Qt::DirectConnection);
        
            pluginWorkerThread->start();
        }
        

        Once the thread is started using this call from another class

        startThread_ = new StartThread();
        startThread_->startThread();
        

        The thread does indeed start so far it is ok.
        In the pluginWorker class which runs under the above thread, I instantiate 2 classes as follows:

        PluginWorker::PluginWorker() :
           selectdatabase_(nullptr)
          ,databaseProcessing_(nullptr)
        {
            std::cout << "STARTING PLUGIN WORKER" << std::endl;
        
            databaseProcessing_ = new DatabaseProcessing(); 
            selectdatabase_ = new SelectDatabase();
        
            //setup communication between selectdatabase_ and databaseProcessing_
            connect(selectdatabase_, SIGNAL(sendDatabaseName(QString)), databaseProcessing_, SLOT(getDatabaseName(QString)));
        
        }
        

        However when I emit from selectDatabase::sendDatabaseName to the slot in databaseProcessing::getDatabaseName nothing is received.

        I'm using Q_Object in both classes for selectDatabase_ and databaseProcessing_

        Below is a include example, both are similar:

        #ifndef DATBASEPROCESSING_H
        #define DATBASEPROCESSING_H
        
        #include <QObject>
        #include <QMainWindow>
        
        class DatabaseProcessing : public QObject
        {
            Q_OBJECT
        
        public:
            DatabaseProcessing();
            virtual ~DatabaseProcessing();
        
        
        public Q_SLOTS:
            void getDatabaseName(QString databaseName);
        };
        

        Would anyone have any idea why the slot is not being called? I really would appreciate any feedback.

        Thanks!

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #2

        @leinad
        Hi. I see you have posted quite a lot in this forum. Would you care to start marking your code blocks inside the forum's Code tags? It's the icon which looks like </>, or put a line of ``` (3 backticks) above and below your blocks. You could edit your post. For my part it would make it a lot easier to see what's going on in your post.

        However when I emit from selectDatabase::sendDatabaseName to the slot in databaseProcessing::getDatabaseName nothing is received.

        Why don't you start by connecting a lambda to the signal so that you know that it's being emitted?

        L 1 Reply Last reply
        0
        • JonBJ JonB

          @leinad
          Hi. I see you have posted quite a lot in this forum. Would you care to start marking your code blocks inside the forum's Code tags? It's the icon which looks like </>, or put a line of ``` (3 backticks) above and below your blocks. You could edit your post. For my part it would make it a lot easier to see what's going on in your post.

          However when I emit from selectDatabase::sendDatabaseName to the slot in databaseProcessing::getDatabaseName nothing is received.

          Why don't you start by connecting a lambda to the signal so that you know that it's being emitted?

          L Offline
          L Offline
          leinad
          wrote on last edited by
          #3

          @JonB Sorry. I fixed using the back tics. Can you explain how I can connect a lambda to the signal?

          Atr0p0sA JonBJ 2 Replies Last reply
          0
          • L leinad

            @JonB Sorry. I fixed using the back tics. Can you explain how I can connect a lambda to the signal?

            Atr0p0sA Offline
            Atr0p0sA Offline
            Atr0p0s
            wrote on last edited by
            #4

            @leinad Here is a good explanation.

            1 Reply Last reply
            0
            • L leinad

              @JonB Sorry. I fixed using the back tics. Can you explain how I can connect a lambda to the signal?

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #5

              @leinad
              That's much more readable, thank you :)

              I didn't want to bring this up, because it likely has nothing to do with your issue, but SIGNAL/SLOT() macros are the old style of Qt connect()s. Unfortunately a lot of examples on the web still use them. The new style was introduced a decade ago as C++ supported it. It is type-safe and gives compile time errors if the slot is not right for the signal.

              connect(signalObject, &SignalClass::method, slotObject, &SlotClass::method);
              

              So for your connect(selectdatabase_, SIGNAL(sendDatabaseName(QString)), databaseProcessing_, SLOT(getDatabaseName(QString)));:

              connect(selectdatabase_, &SelectDatabase::sendDatabaseName, databaseProcessing_, &DatabaseProcessing::getDatabaseName);
              

              Doesn't that look tidier? :) I really suggest you change to this syntax from now onwards.

              You need new-style to use C++ lambdas for the slot. I suggest you try something like:

              connect(selectdatabase_, &SelectDatabase::sendDatabaseName,
                      databaseProcessing_, [](QString databaseName) { qDebug() << "sendDatabaseName" << databaseName; } );
              

              Now we know whether signal is emitted and passes database name. Does this work?

              L 2 Replies Last reply
              0
              • JonBJ JonB

                @leinad
                That's much more readable, thank you :)

                I didn't want to bring this up, because it likely has nothing to do with your issue, but SIGNAL/SLOT() macros are the old style of Qt connect()s. Unfortunately a lot of examples on the web still use them. The new style was introduced a decade ago as C++ supported it. It is type-safe and gives compile time errors if the slot is not right for the signal.

                connect(signalObject, &SignalClass::method, slotObject, &SlotClass::method);
                

                So for your connect(selectdatabase_, SIGNAL(sendDatabaseName(QString)), databaseProcessing_, SLOT(getDatabaseName(QString)));:

                connect(selectdatabase_, &SelectDatabase::sendDatabaseName, databaseProcessing_, &DatabaseProcessing::getDatabaseName);
                

                Doesn't that look tidier? :) I really suggest you change to this syntax from now onwards.

                You need new-style to use C++ lambdas for the slot. I suggest you try something like:

                connect(selectdatabase_, &SelectDatabase::sendDatabaseName,
                        databaseProcessing_, [](QString databaseName) { qDebug() << "sendDatabaseName" << databaseName; } );
                

                Now we know whether signal is emitted and passes database name. Does this work?

                L Offline
                L Offline
                leinad
                wrote on last edited by
                #6

                @JonB
                Thanks, I see. I will give it a try.

                1 Reply Last reply
                0
                • JonBJ JonB

                  @leinad
                  That's much more readable, thank you :)

                  I didn't want to bring this up, because it likely has nothing to do with your issue, but SIGNAL/SLOT() macros are the old style of Qt connect()s. Unfortunately a lot of examples on the web still use them. The new style was introduced a decade ago as C++ supported it. It is type-safe and gives compile time errors if the slot is not right for the signal.

                  connect(signalObject, &SignalClass::method, slotObject, &SlotClass::method);
                  

                  So for your connect(selectdatabase_, SIGNAL(sendDatabaseName(QString)), databaseProcessing_, SLOT(getDatabaseName(QString)));:

                  connect(selectdatabase_, &SelectDatabase::sendDatabaseName, databaseProcessing_, &DatabaseProcessing::getDatabaseName);
                  

                  Doesn't that look tidier? :) I really suggest you change to this syntax from now onwards.

                  You need new-style to use C++ lambdas for the slot. I suggest you try something like:

                  connect(selectdatabase_, &SelectDatabase::sendDatabaseName,
                          databaseProcessing_, [](QString databaseName) { qDebug() << "sendDatabaseName" << databaseName; } );
                  

                  Now we know whether signal is emitted and passes database name. Does this work?

                  L Offline
                  L Offline
                  leinad
                  wrote on last edited by
                  #7

                  @JonB said in Weird issue with SIGNAL/SLOT:

                  connect(signalObject, &SignalClass::method, slotObject, &SlotClass::method);

                  Funny, I use QtCreator with TIDY and it never called it out as a bad style. Perhaps the default options disable it?

                  L 1 Reply Last reply
                  0
                  • L leinad

                    @JonB said in Weird issue with SIGNAL/SLOT:

                    connect(signalObject, &SignalClass::method, slotObject, &SlotClass::method);

                    Funny, I use QtCreator with TIDY and it never called it out as a bad style. Perhaps the default options disable it?

                    L Offline
                    L Offline
                    leinad
                    wrote on last edited by
                    #8

                    @JonB

                    connect(selectdatabase_, &SelectDatabase::sendDatabaseName,
                            databaseProcessing_, [](QString databaseName) { qDebug() << "sendDatabaseName" << databaseName; } );
                    

                    I'm afraid I can't use this lambda function because I don't have access to databaseName, it is a QString which is sent from another object outside of the connect class.

                    L 1 Reply Last reply
                    0
                    • L leinad

                      @JonB

                      connect(selectdatabase_, &SelectDatabase::sendDatabaseName,
                              databaseProcessing_, [](QString databaseName) { qDebug() << "sendDatabaseName" << databaseName; } );
                      

                      I'm afraid I can't use this lambda function because I don't have access to databaseName, it is a QString which is sent from another object outside of the connect class.

                      L Offline
                      L Offline
                      leinad
                      wrote on last edited by
                      #9

                      @JonB
                      Sorry never mind. I can indeed use it.

                      L 1 Reply Last reply
                      0
                      • L leinad

                        @JonB
                        Sorry never mind. I can indeed use it.

                        L Offline
                        L Offline
                        leinad
                        wrote on last edited by
                        #10

                        @leinad
                        So it appears that the lambda does indeed show the correct value passed but yet the SLOT does not show it :(

                        JonBJ 1 Reply Last reply
                        0
                        • L leinad

                          @leinad
                          So it appears that the lambda does indeed show the correct value passed but yet the SLOT does not show it :(

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by
                          #11

                          @leinad
                          This was just the first step. Now we know the signal does get emitted and the connect() attaches to it.

                          Now:

                          connect(selectdatabase_, &SelectDatabase::sendDatabaseName, databaseProcessing_, &DatabaseProcessing::getDatabaseName)
                          

                          (Put a qDebug() << databaseName; as first statement in slot.) I presume you will say the slot does not get called?

                          If not, are selectdatabase_ and databaseProcessing_ in different threads? If so, do you allow the event loop to run (signals across threads are queued)?

                          L 1 Reply Last reply
                          0
                          • JonBJ JonB

                            @leinad
                            This was just the first step. Now we know the signal does get emitted and the connect() attaches to it.

                            Now:

                            connect(selectdatabase_, &SelectDatabase::sendDatabaseName, databaseProcessing_, &DatabaseProcessing::getDatabaseName)
                            

                            (Put a qDebug() << databaseName; as first statement in slot.) I presume you will say the slot does not get called?

                            If not, are selectdatabase_ and databaseProcessing_ in different threads? If so, do you allow the event loop to run (signals across threads are queued)?

                            L Offline
                            L Offline
                            leinad
                            wrote on last edited by
                            #12

                            @JonB
                            I figured out what is happening. Seems the Emit is being called before the connect statement had a chance to be called. I'll have to rearrange how statements get executed.

                            Thanks!

                            1 Reply Last reply
                            0
                            • L leinad has marked this topic as solved on

                            • Login

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