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. signal/slot connection calls wrong instance
Forum Updated to NodeBB v4.3 + New Features

signal/slot connection calls wrong instance

Scheduled Pinned Locked Moved Solved General and Desktop
11 Posts 6 Posters 624 Views 3 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.
  • D Offline
    D Offline
    django.Reinhard
    wrote on last edited by
    #1

    Hi,

    I have some widgets of a class-hierarchy like this:

    class A : public QWidget
    {
    public slots:
      void cbPushButton() {
        QWidget* w = viewStack->page("D");
        D*       d = static_cast<D*>(w);
    
        connect(d, &D::submitResult, this, &A::receiveResult);
        viewStack->activatePage("D");
        }
    
      void receiveResult(QVariant result) {
        QWidget* w = viewStack->page("D");
        D*       d = static_cast<D*>(w);
    
        disconnect(d, &D::submitResult, this, &A::receiveResult);
        processResult(result);
        }
    
      virtual void processResult(QVariant result) {
        ...
        }
      };
    
    class B : public A
    {
      virtual void processResult(QVariant result) override {
        ...
        emit signal4Class_C(...);
        }
      };
    
    class C : public A
    {
      // process signal from class B
      };
    
    class D : public QWidget
    {
    signals:
      void submitResult(QVariant result);
      };
    

    All widgets are added to some stacked layout and all A-C instances use widget class D.

    I suppose, that if I have one instance of A, B, C each, means, that I have 3 different this pointers.

    use-case starts with a pushbutton-callback, which activates class D and waits for some user interaction. Then on certain useraction class D shall submit some result to the calling instance.

    To achieve that, I issue a connect in the pushbuttons callback, which connects the signal of class D with a slot of class A. That slot calls a virtual function of A processResult(), which is overloaded in class B. Only the overloaded function of class B causes some action in instance C.

    That slot-function receiveResult() disconnects the established connection between A and D. At least that is the theory.

    When I start test-sequence using pushbutton of class A, then functions are called in the right sequence and on the right instance and result of class D does not initiate any action in classC.

    Once I select class B and use B's pushbutton to use class D - slot/signal connections got confused and from that on receiveResult is always called on instance B, even if pushbutton was used from class A and connect used this-pointer of A.

    I know its complicated. Don't know, how to ease that stuff.
    Using debugger, callbacks are routed to wrong instance too, but I have to admit, that I don't really understand the moc generated stuff.

    I wanted to implement that function routing by a self written interface, but then I have the problem, that I don't know, how to use QObject functions from my interface. Can't derive interface from QObject, if class is already a subclass of QObject.

    Any idea, how I could escape from trap?

    KroMignonK 1 Reply Last reply
    0
    • D django.Reinhard

      Hi,

      I have some widgets of a class-hierarchy like this:

      class A : public QWidget
      {
      public slots:
        void cbPushButton() {
          QWidget* w = viewStack->page("D");
          D*       d = static_cast<D*>(w);
      
          connect(d, &D::submitResult, this, &A::receiveResult);
          viewStack->activatePage("D");
          }
      
        void receiveResult(QVariant result) {
          QWidget* w = viewStack->page("D");
          D*       d = static_cast<D*>(w);
      
          disconnect(d, &D::submitResult, this, &A::receiveResult);
          processResult(result);
          }
      
        virtual void processResult(QVariant result) {
          ...
          }
        };
      
      class B : public A
      {
        virtual void processResult(QVariant result) override {
          ...
          emit signal4Class_C(...);
          }
        };
      
      class C : public A
      {
        // process signal from class B
        };
      
      class D : public QWidget
      {
      signals:
        void submitResult(QVariant result);
        };
      

      All widgets are added to some stacked layout and all A-C instances use widget class D.

      I suppose, that if I have one instance of A, B, C each, means, that I have 3 different this pointers.

      use-case starts with a pushbutton-callback, which activates class D and waits for some user interaction. Then on certain useraction class D shall submit some result to the calling instance.

      To achieve that, I issue a connect in the pushbuttons callback, which connects the signal of class D with a slot of class A. That slot calls a virtual function of A processResult(), which is overloaded in class B. Only the overloaded function of class B causes some action in instance C.

      That slot-function receiveResult() disconnects the established connection between A and D. At least that is the theory.

      When I start test-sequence using pushbutton of class A, then functions are called in the right sequence and on the right instance and result of class D does not initiate any action in classC.

      Once I select class B and use B's pushbutton to use class D - slot/signal connections got confused and from that on receiveResult is always called on instance B, even if pushbutton was used from class A and connect used this-pointer of A.

      I know its complicated. Don't know, how to ease that stuff.
      Using debugger, callbacks are routed to wrong instance too, but I have to admit, that I don't really understand the moc generated stuff.

      I wanted to implement that function routing by a self written interface, but then I have the problem, that I don't know, how to use QObject functions from my interface. Can't derive interface from QObject, if class is already a subclass of QObject.

      Any idea, how I could escape from trap?

      KroMignonK Offline
      KroMignonK Offline
      KroMignon
      wrote on last edited by
      #2

      @django-Reinhard

      You have to add Q_OBJECT in the private section of each class which implements it own signals or slots (cf. https://doc.qt.io/qt-5/qobject.html#Q_OBJECT)

      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

      1 Reply Last reply
      0
      • D Offline
        D Offline
        django.Reinhard
        wrote on last edited by
        #3

        Thank you for your attention!

        @KroMignon said in signal/slot connection calls wrong instance:

        you have to add Q_OBJECT in

        Sorry, but that's to obvious. Of cause I have done so.
        I have omitted the self-evident to clarify the problem

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

          Hi,

          The behaviour is correct. Your class B inherits from A and overloads the slot. So the connection is done on the instance of B and will call the corresponding overload. If you want to call the base class implementation either do it from class B overloaded slot or use a different method.

          By the way, you should use qobject_cast when cast QObject based classes.

          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
          3
          • D Offline
            D Offline
            django.Reinhard
            wrote on last edited by
            #5

            @SGaist said in signal/slot connection calls wrong instance:

            The behaviour is correct.

            NO!
            If I use instance of A for a connection, then there is nothing from B at that instance. So can't be correct!

            @SGaist said in signal/slot connection calls wrong instance:

            By the way, you should use qobject_cast when cast QObject based classes.

            Thanks for the hint! Didn't know that.
            Gonna look for that

            jsulmJ 1 Reply Last reply
            0
            • D django.Reinhard

              @SGaist said in signal/slot connection calls wrong instance:

              The behaviour is correct.

              NO!
              If I use instance of A for a connection, then there is nothing from B at that instance. So can't be correct!

              @SGaist said in signal/slot connection calls wrong instance:

              By the way, you should use qobject_cast when cast QObject based classes.

              Thanks for the hint! Didn't know that.
              Gonna look for that

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

              @django-Reinhard said in signal/slot connection calls wrong instance:

              If I use instance of A for a connection, then there is nothing from B at that instance.

              Didn't you say that you're using class B?
              I quote you:
              "Once I select class B and use B's pushbutton to use class D - slot/signal connections got confused and from that on receiveResult is always called on instance B". So, why should it not call the overloaded slot in class B if you're using class B?

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

              1 Reply Last reply
              0
              • D Offline
                D Offline
                django.Reinhard
                wrote on last edited by
                #7

                @jsulm said in signal/slot connection calls wrong instance:

                Didn't you say that you're using class B?

                Sorry, I'm not that stupid to report a problem for working as designed.

                Obviously my english is not good enuf to explain what I mean.

                @jsulm said in signal/slot connection calls wrong instance:

                Once I select class B and use B's pushbutton to use class D - slot/signal connections got confused and from that on receiveResult is always called on instance B

                That means, "once I select class B and use B's pushbutton ..." then on using class A again (using pushbutton from A-instance), connection between class A and class D ALWAYS calls instance B when D emits the signal.

                Hope its clear now.

                I have 3 instances: A, B, C - all derived from class A. Pushbutton and slot functions are all in class A.
                No overriding of slot-function.

                But slot function calls another function, which is overloaded in class B (and in class B only).

                In the callback of the pushbutton connection between A, B, C and class D is established (called connect - but each instance has different this-pointer, so there is already a unique property.
                slot-function which gets called on emitting signal then removes the connection.

                class D fires the event (emits signal function) and this signal should use established connection, but uses a connection from former use-case.

                kshegunovK 1 Reply Last reply
                0
                • D django.Reinhard

                  @jsulm said in signal/slot connection calls wrong instance:

                  Didn't you say that you're using class B?

                  Sorry, I'm not that stupid to report a problem for working as designed.

                  Obviously my english is not good enuf to explain what I mean.

                  @jsulm said in signal/slot connection calls wrong instance:

                  Once I select class B and use B's pushbutton to use class D - slot/signal connections got confused and from that on receiveResult is always called on instance B

                  That means, "once I select class B and use B's pushbutton ..." then on using class A again (using pushbutton from A-instance), connection between class A and class D ALWAYS calls instance B when D emits the signal.

                  Hope its clear now.

                  I have 3 instances: A, B, C - all derived from class A. Pushbutton and slot functions are all in class A.
                  No overriding of slot-function.

                  But slot function calls another function, which is overloaded in class B (and in class B only).

                  In the callback of the pushbutton connection between A, B, C and class D is established (called connect - but each instance has different this-pointer, so there is already a unique property.
                  slot-function which gets called on emitting signal then removes the connection.

                  class D fires the event (emits signal function) and this signal should use established connection, but uses a connection from former use-case.

                  kshegunovK Offline
                  kshegunovK Offline
                  kshegunov
                  Moderators
                  wrote on last edited by kshegunov
                  #8

                  @django-Reinhard said in signal/slot connection calls wrong instance:

                  I have 3 instances: A, B, C - all derived from class A. Pushbutton and slot functions are all in class A.
                  No overriding of slot-function.

                  Instances, like objects, correct? I mean, because reading the text it does seem to me like you're mixing the meaning of classes and objects. Like here:

                  In the callback of the pushbutton connection between A, B, C and class D is established

                  Connections are established between objects, not between classes. So in the end are A, B, C and D objects or classes?

                  But slot function calls another function, which is overloaded in class B (and in class B only).

                  Overridden. It's a virtual.

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply
                  1
                  • D Offline
                    D Offline
                    django.Reinhard
                    wrote on last edited by
                    #9

                    @kshegunov said in signal/slot connection calls wrong instance:

                    I mean, because reading the text it does seem to me like you're mixing the meaning of classes and objects.

                    YES SIR!

                    I'm far from being perfekt :(

                    Maybe my behavior is wrong. I don't know.

                    When I discover behavior in my work that doesn't align with my expectations, I seek contact with other developers to clarify whether I've made a mistake or found a bug caused by others.

                    With new material, like now with my first Qt project, I simply can't assess if it's me or not.

                    So I appreciate any hint on how to become better :)

                    jeremy_kJ 1 Reply Last reply
                    0
                    • D django.Reinhard

                      @kshegunov said in signal/slot connection calls wrong instance:

                      I mean, because reading the text it does seem to me like you're mixing the meaning of classes and objects.

                      YES SIR!

                      I'm far from being perfekt :(

                      Maybe my behavior is wrong. I don't know.

                      When I discover behavior in my work that doesn't align with my expectations, I seek contact with other developers to clarify whether I've made a mistake or found a bug caused by others.

                      With new material, like now with my first Qt project, I simply can't assess if it's me or not.

                      So I appreciate any hint on how to become better :)

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

                      @django-Reinhard said in signal/slot connection calls wrong instance:

                      Maybe my behavior is wrong. I don't know.

                      It would be a lot easier to determine with minimal working code instead of a natural language explanation of the code.

                      Note that minimal and working means that all of the important things like Q_OBJECT macros need to be there. Commented out code, unrelated object instances, ellipses, and other things not related to the problem should not be present. If it doesn't compile or produce the desired compiler failure for you, it won't for anyone else.

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

                      1 Reply Last reply
                      1
                      • D Offline
                        D Offline
                        django.Reinhard
                        wrote on last edited by
                        #11

                        Just to close this:

                        I rearranged my code so that I don't need to cast interface pointer and removed Qt-signal connections. Works perfect with own written Interface-callbacks.

                        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