Connection Signal/Slot not working (with window "separation")
-
I had already created a small application under Qt but now I have to develop a slightly more complex application.
An application with specific and distinct treatments accessible by a menu.
So I tried to separate my treatments, my windows.
It allows me not to have everything in my "MyMainWindow.h" and "MyMainWindow.cpp" files
I don't know if the method I'm using is the right one but I'm passing a pointer from my Main Window to my Specific Window.In principle it works. But is this already the right solution...?
And it works but when I want to create a Signal/Slot connection in a window, nothing happens.
The slot is indeed found (otherwise I would get an error) but nothing happens.
Example with the Signal/Slot connection from the "MyXWindow.cpp" page below:connect(buttonPage,SIGNAL(clicked(bool)),this,SLOT(doSpecificTreatment()));I am posting my (part of my) code below (and it is also available complete on gitHub)
https://github.com/JuanDeDironne/qt_example_projectmain.cpp
#include<QApplication> #include"MyMainWindow.h" int main(int nbArg, char* argList[]) { QApplication myApp(nbArg,argList); MyMainWindow myWindow; myWindow.show(); myApp.exec(); }MyMainWindow.h
#ifndef MYMAINWINDOW_H #define MYMAINWINDOW_H #include<QtWidgets> class MyMainWindow : public QMainWindow { Q_OBJECT public: MyMainWindow(); public slots: void launchXWindow(); void launchYWindow(); private: QAction *m_actionQuit; QAction *m_actionX; QAction *m_actionY; QMenu *m_menuFile; }; #endif // MYMAINWINDOW_HMyMainWindow.cpp
#include"MyMainWindow.h" #include"MyXWindow.h" #include"MyYWindow.h" MyMainWindow::MyMainWindow() { // Initialization Window setWindowTitle("My Example Software"); setMinimumHeight(500); setMinimumWidth(500); // Definition Actions m_actionQuit = new QAction(QIcon("./icones/icone_quit.png"),"Quit",this); m_actionX = new QAction(QIcon("./icones/icone_perso.png"),"X Window",this); m_actionY = new QAction(QIcon("./icones/icone_configuration.png"),"Y Window",this); // Définition Menu m_menuFile = menuBar()->addMenu("File"); m_menuFile->addAction(m_actionX); m_menuFile->addAction(m_actionY); m_menuFile->addAction(m_actionQuit); // Creation Connections connect(m_actionQuit,SIGNAL(triggered(bool)),qApp,SLOT(quit())); connect(m_actionX,SIGNAL(triggered(bool)),this,SLOT(launchXWindow())); connect(m_actionY,SIGNAL(triggered(bool)),this,SLOT(launchYWindow())); } void MyMainWindow::launchXWindow() { MyXWindow currentWindow; currentWindow.displayWindow(this); } void MyMainWindow::launchYWindow() { MyYWindow currentWindow; currentWindow.displayWindow(this); }MyMainWindow.h
#ifndef MYXWINDOW_H #define MYXWINDOW_H #include"MyMainWindow.h" class MyXWindow : public QWidget { Q_OBJECT public: MyXWindow(); void displayWindow(MyMainWindow*); public slots: void doSpecificTreatment(); private: QString myParameterA; QString myParameterB; }; #endif // MYXWINDOW_HMyMainWindow.cpp
#include"MyXWindow.h" MyXWindow::MyXWindow() { } void MyXWindow::displayWindow(MyMainWindow* windowFonc) { // Initialization QWidget *widgetPage; widgetPage = new QWidget(); QGridLayout *layoutPage; layoutPage = new QGridLayout(); layoutPage->setAlignment(Qt::AlignCenter); QPushButton *buttonPage; buttonPage = new QPushButton("Submit"); // Add Label and Button layoutPage->addWidget(new QLabel("Here Interface of <b>X</b> Window")); layoutPage->addWidget(buttonPage); // Association Layout to Widget and Placement widgetPage->setLayout(layoutPage); windowFonc->setCentralWidget(widgetPage); // Creation Connection - DOES NOT WORK :( connect(buttonPage,SIGNAL(clicked(bool)),this,SLOT(doSpecificTreatment())); } void MyXWindow::doSpecificTreatment() { qDebug() << "Here X Treatment"; } -
I had already created a small application under Qt but now I have to develop a slightly more complex application.
An application with specific and distinct treatments accessible by a menu.
So I tried to separate my treatments, my windows.
It allows me not to have everything in my "MyMainWindow.h" and "MyMainWindow.cpp" files
I don't know if the method I'm using is the right one but I'm passing a pointer from my Main Window to my Specific Window.In principle it works. But is this already the right solution...?
And it works but when I want to create a Signal/Slot connection in a window, nothing happens.
The slot is indeed found (otherwise I would get an error) but nothing happens.
Example with the Signal/Slot connection from the "MyXWindow.cpp" page below:connect(buttonPage,SIGNAL(clicked(bool)),this,SLOT(doSpecificTreatment()));I am posting my (part of my) code below (and it is also available complete on gitHub)
https://github.com/JuanDeDironne/qt_example_projectmain.cpp
#include<QApplication> #include"MyMainWindow.h" int main(int nbArg, char* argList[]) { QApplication myApp(nbArg,argList); MyMainWindow myWindow; myWindow.show(); myApp.exec(); }MyMainWindow.h
#ifndef MYMAINWINDOW_H #define MYMAINWINDOW_H #include<QtWidgets> class MyMainWindow : public QMainWindow { Q_OBJECT public: MyMainWindow(); public slots: void launchXWindow(); void launchYWindow(); private: QAction *m_actionQuit; QAction *m_actionX; QAction *m_actionY; QMenu *m_menuFile; }; #endif // MYMAINWINDOW_HMyMainWindow.cpp
#include"MyMainWindow.h" #include"MyXWindow.h" #include"MyYWindow.h" MyMainWindow::MyMainWindow() { // Initialization Window setWindowTitle("My Example Software"); setMinimumHeight(500); setMinimumWidth(500); // Definition Actions m_actionQuit = new QAction(QIcon("./icones/icone_quit.png"),"Quit",this); m_actionX = new QAction(QIcon("./icones/icone_perso.png"),"X Window",this); m_actionY = new QAction(QIcon("./icones/icone_configuration.png"),"Y Window",this); // Définition Menu m_menuFile = menuBar()->addMenu("File"); m_menuFile->addAction(m_actionX); m_menuFile->addAction(m_actionY); m_menuFile->addAction(m_actionQuit); // Creation Connections connect(m_actionQuit,SIGNAL(triggered(bool)),qApp,SLOT(quit())); connect(m_actionX,SIGNAL(triggered(bool)),this,SLOT(launchXWindow())); connect(m_actionY,SIGNAL(triggered(bool)),this,SLOT(launchYWindow())); } void MyMainWindow::launchXWindow() { MyXWindow currentWindow; currentWindow.displayWindow(this); } void MyMainWindow::launchYWindow() { MyYWindow currentWindow; currentWindow.displayWindow(this); }MyMainWindow.h
#ifndef MYXWINDOW_H #define MYXWINDOW_H #include"MyMainWindow.h" class MyXWindow : public QWidget { Q_OBJECT public: MyXWindow(); void displayWindow(MyMainWindow*); public slots: void doSpecificTreatment(); private: QString myParameterA; QString myParameterB; }; #endif // MYXWINDOW_HMyMainWindow.cpp
#include"MyXWindow.h" MyXWindow::MyXWindow() { } void MyXWindow::displayWindow(MyMainWindow* windowFonc) { // Initialization QWidget *widgetPage; widgetPage = new QWidget(); QGridLayout *layoutPage; layoutPage = new QGridLayout(); layoutPage->setAlignment(Qt::AlignCenter); QPushButton *buttonPage; buttonPage = new QPushButton("Submit"); // Add Label and Button layoutPage->addWidget(new QLabel("Here Interface of <b>X</b> Window")); layoutPage->addWidget(buttonPage); // Association Layout to Widget and Placement widgetPage->setLayout(layoutPage); windowFonc->setCentralWidget(widgetPage); // Creation Connection - DOES NOT WORK :( connect(buttonPage,SIGNAL(clicked(bool)),this,SLOT(doSpecificTreatment())); } void MyXWindow::doSpecificTreatment() { qDebug() << "Here X Treatment"; }@Juan-de-Dironne said in Connection Signal/Slot not working (with window "separation"):
void MyMainWindow::launchXWindow() { MyXWindow currentWindow; currentWindow.displayWindow(this); } void MyMainWindow::launchYWindow() { MyYWindow currentWindow; currentWindow.displayWindow(this); }Do you understand that those instances are immediately destroyed once
displayWindow()returns? -
@Juan-de-Dironne said in Connection Signal/Slot not working (with window "separation"):
void MyMainWindow::launchXWindow() { MyXWindow currentWindow; currentWindow.displayWindow(this); } void MyMainWindow::launchYWindow() { MyYWindow currentWindow; currentWindow.displayWindow(this); }Do you understand that those instances are immediately destroyed once
displayWindow()returns?@JonB My method to separate my different windows in H and CPP file is not the right one...?
And your remark on the destruction of instances explains the fact that the connect() does not work...?The connection established between the signal and the slot cannot work because...?
The connect() function is called on the "currentWindow" Widget of type "MyXWindow" but it no longer exists when I click on it...?
Basically that's it...? -
@JonB My method to separate my different windows in H and CPP file is not the right one...?
And your remark on the destruction of instances explains the fact that the connect() does not work...?The connection established between the signal and the slot cannot work because...?
The connect() function is called on the "currentWindow" Widget of type "MyXWindow" but it no longer exists when I click on it...?
Basically that's it...?@Juan-de-Dironne said in Connection Signal/Slot not working (with window "separation"):
My method to separate my different windows in H and CPP file is not the right one...?
@JonB did not write that.
"And your remark on the destruction of instances explains the fact that the connect() does not work...?" - yes, because currentWindow is destroyed as soon as launchXWindow or launchYWindow terminate. This is basic C++ (read about variable scopes). -
@JonB My method to separate my different windows in H and CPP file is not the right one...?
And your remark on the destruction of instances explains the fact that the connect() does not work...?The connection established between the signal and the slot cannot work because...?
The connect() function is called on the "currentWindow" Widget of type "MyXWindow" but it no longer exists when I click on it...?
Basically that's it...?@Juan-de-Dironne
Think about scope in C++.void MyMainWindow::launchYWindow() { MyYWindow currentWindow; currentWindow.displayWindow(this); }MyYWindow currentWindowis a local variable (on the stack) to this method. That means once the function exits any local variables are destroyed.displayWindow(MyMainWindow* windowFonc)seems to create some widgets which it places onto the passed-inMyMainWindow. It is odd to have a class/instance to do this, and to keep replacing thesetCentralWidget(), but that probably "works". However it also goes// Creation Connection - DOES NOT WORK :( connect(buttonPage,SIGNAL(clicked(bool)),this,SLOT(doSpecificTreatment()));The slot, with
doSpecificTreatment(), is placed on objectthis, which is thecurrentWindowinlaunchYWindow(). But as soon asdisplayWindow()exits so doeslaunchYWindow(), takingMyYWindow currentWindowwith it. When a slot (or signal) object goes out of scope/is destroyed Qt disconnects any slots or signals on that object. That looks like why yourconnect()shows no effect.In a word, you probably want to look at using a QStackedWidget for the central widget on your
MyMainWindowif you want to change its content rather than altering its central widget. Your X/Y windows would be pages on the stacked widget, which shows just any one at a time. You will allocate them on the heap (i.e.new), just once, so they will persist even when not visible. -
@JonB and @jsulm Thank you for your answers. It's really a C++ variable scoping issue actually.
My method to separate windows or features into different files is not workable I feel. Are there any tutorials on this?
Or the solution proposed by @JonB (which I thank myself again) is the solution for a complex application with different functionalities requiring different interfaces...?
The use of "QStackedWidget" is necessary because we do not usually change the central widget to display different windows..?
-
@JonB and @jsulm Thank you for your answers. It's really a C++ variable scoping issue actually.
My method to separate windows or features into different files is not workable I feel. Are there any tutorials on this?
Or the solution proposed by @JonB (which I thank myself again) is the solution for a complex application with different functionalities requiring different interfaces...?
The use of "QStackedWidget" is necessary because we do not usually change the central widget to display different windows..?
@Juan-de-Dironne said in Connection Signal/Slot not working (with window "separation"):
My method to separate windows or features into different files is not workable I feel
Separating functionality and also windows/widgets in separate files is common approach and works. You just need to make sure your objects live as long as they are needed. To achieve this either allocate them on the heap or make them member variables.
-
@Juan-de-Dironne said in Connection Signal/Slot not working (with window "separation"):
My method to separate windows or features into different files is not workable I feel
Separating functionality and also windows/widgets in separate files is common approach and works. You just need to make sure your objects live as long as they are needed. To achieve this either allocate them on the heap or make them member variables.
@jsulm "Separating functionality and also windows/widgets in separate files is common approach and works"
But not using the principle that I implemented with an "Annex Window" which only changes the central Widget of the Main Window.
This solution requires interactions between classes that seem difficult to achieve.
Are there any tutorials on this? -
@jsulm "Separating functionality and also windows/widgets in separate files is common approach and works"
But not using the principle that I implemented with an "Annex Window" which only changes the central Widget of the Main Window.
This solution requires interactions between classes that seem difficult to achieve.
Are there any tutorials on this?@Juan-de-Dironne said in Connection Signal/Slot not working (with window "separation"):
This solution requires interactions between classes that seem difficult to achieve
Why difficult? Wha texactly is difficult?
In Qt you can also use signals/slots to communicate between different classes. -
@Juan-de-Dironne said in Connection Signal/Slot not working (with window "separation"):
This solution requires interactions between classes that seem difficult to achieve
Why difficult? Wha texactly is difficult?
In Qt you can also use signals/slots to communicate between different classes.@jsulm I can keep my method but I have to change the code of my "launchYWindow" function if I want it to work. With the following code :
The Code Before
void MyMainWindow::launchYWindow() { MyYWindow currentWindow; currentWindow.displayWindow(this); }The Code After
void MyMainWindow::launchXWindow() { MyXWindow *currentWindow; currentWindow = new MyXWindow(); currentWindow->displayWindow(this); }This code works. I allocate my Widget on the heap as you said above.
But is it better to do that or use the "stackedWidget"...? -
@jsulm I can keep my method but I have to change the code of my "launchYWindow" function if I want it to work. With the following code :
The Code Before
void MyMainWindow::launchYWindow() { MyYWindow currentWindow; currentWindow.displayWindow(this); }The Code After
void MyMainWindow::launchXWindow() { MyXWindow *currentWindow; currentWindow = new MyXWindow(); currentWindow->displayWindow(this); }This code works. I allocate my Widget on the heap as you said above.
But is it better to do that or use the "stackedWidget"...?@Juan-de-Dironne
Stacked widget, for several reasons. Including that you are leaking a widget every time you do it your way. -
Thank you very much for your answers and your time spent.
-
J Juan de Dironne referenced this topic on