Hello. I'm trying to write the following application in QT. There is a main window in which the Menu widget is set as the main widget. It selects which widget to make the main one and the corresponding button is pressed. The signal is connected to the slot of the main window, which installs another widget as a new main window. This new widget has its own button, which, when clicked, actually draws a menu widget in the main window. The problem is that when you click this button in a new widget, the program "unexpectedly ends." Tell me, what is my problem? Actually File with classes lib.h

#ifndef LIB_H #define LIB_H #include <QApplication> #include <QWidget> #include <QMainWindow> #include <QPushButton> #include <QVBoxLayout> //Виджет меню class Menu: public QWidget { Q_OBJECT private: QPushButton *button1; QPushButton *button2; QPushButton *button3; QVBoxLayout *layout; public: Menu(QWidget *); ~Menu(); signals: void sig_first_widget(); void sig_second_widget(); void sig_exit(); }; //Первый виджет class FirstWidget: public QWidget { Q_OBJECT private: QPushButton *button; QVBoxLayout *layout; public: FirstWidget(QWidget*); ~FirstWidget(); signals: void set_menu(); }; //Второй виджет class SecondWidget: public QWidget { Q_OBJECT private: QPushButton *button; QVBoxLayout *layout; public: SecondWidget(QWidget*); ~SecondWidget(); signals: void set_menu(); }; //Главное окно class MainWindow : public QMainWindow { Q_OBJECT private: Menu *menu; FirstWidget *first; SecondWidget *second; public: MainWindow(QWidget *parent = 0); ~MainWindow(); public slots: void set_first(); void set_second(); void set_menu(); }; #endif // LIB_H 

The implementation of classes and the main () function:

 #include "lib.h" // Menu::Menu(QWidget *parent): QWidget(parent) { button1 = new QPushButton("set_first_widget"); button2 = new QPushButton("set_second_widget"); button3 = new QPushButton("exit"); layout = new QVBoxLayout; layout->addWidget(button1); layout->addWidget(button2); layout->addWidget(button3); this->setLayout(layout); connect(button1, SIGNAL(clicked()), this, SIGNAL(sig_first_widget())); connect(button2, SIGNAL(clicked()), this, SIGNAL(sig_second_widget())); connect(button3, SIGNAL(clicked()), this, SIGNAL(sig_exit())); } // Menu::~Menu() { delete button1; delete button2; delete button3; delete layout; } // FirstWidget::FirstWidget(QWidget *parent): QWidget(parent) { button = new QPushButton("This is the first widget"); layout = new QVBoxLayout; layout->addWidget(button); this->setLayout(layout); connect(button, SIGNAL(clicked()), this, SIGNAL(set_menu())); } // FirstWidget::~FirstWidget() { delete button; delete layout; } // SecondWidget::SecondWidget(QWidget *parent): QWidget(parent) { button = new QPushButton("This is the second widget"); layout = new QVBoxLayout; layout->addWidget(button); this->setLayout(layout); connect(button, SIGNAL(clicked()), this, SIGNAL(set_menu())); } // SecondWidget::~SecondWidget() { delete button; delete layout; } // MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) { menu = new Menu(this); first = new FirstWidget(this); second = new SecondWidget(this); this->setCentralWidget(menu); connect(menu, SIGNAL(sig_exit()), this, SLOT(close())); connect(menu, SIGNAL(sig_first_widget()), this, SLOT(set_first())); connect(menu, SIGNAL(sig_second_widget()), this, SLOT(set_second())); connect(first, SIGNAL(set_menu()), this, SLOT(set_menu())); connect(second, SIGNAL(set_menu()), this, SLOT(set_menu())); } // MainWindow::~MainWindow() { delete menu; delete first; delete second; } // void MainWindow::set_first() { this->setCentralWidget(first); } // void MainWindow::set_second() { this->setCentralWidget(second); } // void MainWindow::set_menu() { this->setCentralWidget(menu); } //----------------------------------------------------- int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow *w = new MainWindow(0); w->show(); return a.exec(); } 

    2 answers 2

    The documentation for setCentralWidget says:

     void QMainWindow::setCentralWidget ( QWidget * widget ) Sets the given widget to be the main window's central widget. Note: QMainWindow takes ownership of the widget pointer and deletes it at the appropriate time. 

    Pay attention to the remark. CentralWidget is not a regular container, replacing its contents with another widget, you destroy the original one. This is clearly seen in the debugger. When calling this->setCentralWidget(first); you first get into the destructor of the Menu class.

    Changing the contents of CentralWidget is not a good practice.

      I think that this approach is suitable for your task: - create your CentralWidget class, a QWidget descendant - set it with QStackedLayout - place all the widgets you need in this layout and link the menu actions with a slot that looks like this:

       void chooseWidget() { QStackedLayout *sl = qobject_cast<QStackedLayout*>(centranWidget().layout()); sl->setCurrentWidget(...) } 

      Naturally, I lowered error checking