signal/slot connection calls wrong instance
-
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?
-
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) -
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 -
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.
-
@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 -
@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? -
@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.
-
@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.
-
@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 :)
-
@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.
-
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.