Search code examples
c++qtqwidgetqtguiqstackedwidget

How to change contents of QMainWindow dynamically


I have a QMainWindow that starts out with nothing but a menubar with a menu that has two options. When the first is clicked the window should be populated with QLabels and various input widgets to recieve data. When the second option is clicked the window should be populated with a QTextEdit(obviously removing whatever was on the window at the time)

The following is code I have tried :

void OrderWindow::displayAddOrder(){
     QVBoxLayout* tlayout = new QVBoxLayout();
     QHBoxLayout* row = new QHBoxLayout();
     row->addWidget(nameLbl);
     tlayout->addLayout(row);
     qDeleteAll(children());
     delete layout();
     setLayout(tlayout);
}

It's a bit messy since I've been trying various things. When I click on a menu option with this code it simply says the application has stopped working.

Any help would be appreciated.


Solution

  • You have at least the following options:

    • Always show the actual widget, and hide the rest. This is simple in case of two widgets like in your example. You could use this technique with the observer design pattern for any number of widgets.

    • Use the QStackedWidget class which basically behaves the way as your custom observer pattern implementation would be, although you will need to use an extra class for this.

    Therefore, I would suggest to write the following code:

    orderwindow.h

    ...
    class QStackedWidget;
    class OrderWindow
    {
        ...
    public:
        explicit OrderedWindow(QWidget *parent);
        ...
     private:
         QStackedWidget m_stackedWidget;
        ...
    }
    ...
    

    orderwindow.cpp

    #include "orderwindow.h"
    
    #include <QStackedWidget>
    ...
    
    OrderWindow::OrderWindow(QWidget *parent)
        : QWidget(parent)
        ,  m_stackedWidget(new QStackedWidget(this))
    {
        QWidget *firstPageWidget = new QWidget;
        QWidget *secondPageWidget = new QWidget;
    
        m_stackedWidget->addWidget(firstPageWidget);
        m_stackedWidget->addWidget(secondPageWidget);
    
        QVBoxLayout *layout = new QVBoxLayout;
        layout->addWidget(stackedWidget);
        setLayout(layout);
    }
    
    ...
    
    void OrderWindow::displayAddOrder() {
        m_stackedWidget->setCurrentWidget(nameLbl);
    }
    
    ...