Signal/Slot connection not working when connected in constructor
-
Hi,
I want to connect some signals to some slots in an application of mine. In this very situation, this does NOT work when the connection is established in the constructor, but is DOES work when it is done somewhere later in the program logic (e.g. in a slot called after a button click).
I explain the situation with some example code:
I have a dll that declares a Qt plugin (class MyObject) that inherits from MySignalInterface.
MyObject owns MySubObject, that inherits from MySlotInterface.
Compiling/building/loading the plugin all works fine. When I now want to connect the mySignal from MyObject to mySlot from MySubObject in the constructor of MyObject, the slot is not called when the signal is emitted (I checked that the signal is emitted by setting a breakpoint in the respective moc_MyObject.cpp). When I connect somewhere later (within onButtonPress()), the connection works. There is no output on the command line regarding failed signal/slot connections, and the result value from the call to connect() in the constructor is true.
I don't know how to investigate what is going wrong here with the connections. How to debug this?Below, some code fragments for clarification. Any help would be appreciated.
I am working on Windows10 with Visual Studio 2015 and Qt 5.10.0.MyObject.cpp
MyObject::MyObject() : mySubObject(new MySubObject()) { connectSignals(); // connection does not work; slot is not called when signal is emitted } void MyObject::connectSignals() { connect(this, &MyObject::mySignal, mySubObject, &MySubObject::mySlot); } void MyObject::onButtonPress() // called i.e. in response to a button press { connectSignals(); // connection works, slot is called when signal is emitted }
MyObject.h
class MYOBJECTMODULE_EXPORT MyObject final : public QObject, public MySignalInterface { Q_OBJECT Q_PLUGIN_METADATA(IID "MyObject" FILE "myobject.json") Q_INTERFACES(MySignalInterface) public: MyObject(); signals: void mySignal() override; // from MySignalInterface public slots: void onButtonPress(); private: MySubObject* mySubObject; void connectSignals(); };
MySignalInterface.h
class MySignalInterface { public: // signals: virtual void mySignal() = 0; }; QT_BEGIN_NAMESPACE #define MySignalInterface_iid "MySignalInterface/1.0" Q_DECLARE_INTERFACE(MySignalInterface, MySignalInterface_iid) QT_END_NAMESPACE
MySubObject.h
class MySubObject : public QMainWindow, public MySlotInterface { Q_OBJECT public: MySubObject(QWidget *parent = Q_NULLPTR, Qt::WindowFlags flags = Qt::WindowFlags()); public slots: virtual void mySlot() override; };
MySlotInterface.h
class MySlotInterface { public: // public slots: virtual void mySlot() = 0; }; QT_BEGIN_NAMESPACE #define MySlotInterface_iid "MySlotInterface/1.0" Q_DECLARE_INTERFACE(MySlotInterface, MySlotInterface_iid) QT_END_NAMESPACE
-
After a long investigation the embarrassing truth: I called disconnect() at a place in my code without clearly considering which signals are actually disconnected here.
Just a short explanation: I have a top-level application that loads plugins, with each plugin having a main class. The top-level application connects the signals of the main classes of the plugins together to form a pipeline. Whenever the pipeline is updated, the previous connections between the modules have to be cleared before being connected again. For this purpose I called disconnect() for every top-level class of the loaded modules. What I didn't bear in mind was that this call also disconnected the signals of a main module directed to their sub-modules.
Thank you anyway for your support!
-
@rprueckl said in Signal/Slot connection not working when connected in constructor:
mySubObject
you probably
new
(instantiate) mySubObject() after the connect call. -
@rprueckl said in Signal/Slot connection not working when connected in constructor:
thanks for the quick input. I just checked (by setting a breakpoint in the constructor of MySubObject) - it is only called once.
and what would that tell you ?
You can't even definitely say, if the object is initialized or not, because you don't assign the member pointer to null (initially)
MySubObject* mySubObject;
So even when debugging you may see something != 0, but the object is still not initialized.
-
Hi,
Where exactly are you emitting that signal ?
-
The breakpoint in the constructor of mySubObject is hit because mySubObject is created in the member initialization list of MyObject.
MyObject::MyObject() : mySubObject(new MySubObject())
which is before the call to connect. After this, the constructor of mySubObject is not called anymore, which tells me that there is no second object constructed anywhere.
As I don't encounter a std::bad_alloc exception, I assume the object is correctly created. -
@SGaist
The origin of the signal is in another plugin, which implements a counterpart of the interface of the plugin in question. The signals of the two plugins are connected in the host application, which loads the plugins.
So it is:Plugin2(dll2) mySignal() --> myObject(dll1) mySignal() --> mySubObject(dll1) mySlot()
-
Can you provide a minimal compilable project that shows that issue ?
-
After a long investigation the embarrassing truth: I called disconnect() at a place in my code without clearly considering which signals are actually disconnected here.
Just a short explanation: I have a top-level application that loads plugins, with each plugin having a main class. The top-level application connects the signals of the main classes of the plugins together to form a pipeline. Whenever the pipeline is updated, the previous connections between the modules have to be cleared before being connected again. For this purpose I called disconnect() for every top-level class of the loaded modules. What I didn't bear in mind was that this call also disconnected the signals of a main module directed to their sub-modules.
Thank you anyway for your support!