Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Is changing a QWizard into a QStackedWidget the best option?

Is changing a QWizard into a QStackedWidget the best option?

Scheduled Pinned Locked Moved Unsolved General and Desktop
qt 4.8.5qt 4.8qwizardqstackedwidget
12 Posts 2 Posters 5.4k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    roseicollis
    wrote on 12 May 2016, 11:07 last edited by
    #1

    Hi,

    I've made a program with Qt Creator 4.8.5 that is a configuration program (a Wizard) with the QWizard structure (plus like 30 QWizardPages). It works fine now but I had a lot of problems because I needed a different behaviour for my program than the QWizard allows me in some cases so some people told me to use the class QStackedWidget.
    Now I'm trying to figure if QStackedWidget class is what I really need (in case I had to do the program again) or maybe use another different class, or just use again the QWizard class.... so hope you can help me figuring this out.

    The idea of my program is that it has a lot of pages with a lot of Widgets on them (QLabels, Qcombobox, QPushButtons... ) depending on the page the user is. Moreover, as you know QWizard has its own buttons (NextButton, BackButton, FinishButton, CustomButtonX) to let you move between pages which is really nice BUT with that I had some problems as I need them in some pages but I don't need them or at least not all of them in some other pages. I add some examples of three different pages: Page1 Page2 Page3

    The worst problems I had with QWizard:

    • Can't change easily the QWizard buttons (I managed doing it but iwth a lot of problems and making code not really easy to mantain)
    • Can't jump from one page to another as I want as in some cases you get the "Page x: Already met" error (very important)

    So... do you think that I shoudl really change it to a QStackedWidget? If yes I have a doubt here... as the documentation says: "The QStackedWidget class provides a stack of widgets where only one widget is visible at a time." So that means that my Widget in this case will be my pages and so I need a class derived from QWidget like for example QWizardPage so... should I use QWizardPage as my pages class or is there any other class that fits best here ? (As I don't need all the logic QWizardPage has as ::nextId(), ::validatePage(), ::cleanup() functions that are related to the base QWizard)

    Thank you so much for your help and hope I explain my problem correctly.

    1 Reply Last reply
    0
    • M Offline
      M Offline
      mrjj
      Lifetime Qt Champion
      wrote on 12 May 2016, 11:20 last edited by mrjj 5 Dec 2016, 11:23
      #2

      Hi
      The Stackedwidget is super for such design.
      The widget it talks about is a page.
      so u get all the pages u want and on each page,
      u can have all the widgets u like.

      Normally the page is a plain
      qwidget but u can use own page if u need but
      often there is no need.

      ps. if you use UI files, you can visually manage all the pages. very handy.

      R 1 Reply Last reply 12 May 2016, 11:43
      3
      • M mrjj
        12 May 2016, 11:20

        Hi
        The Stackedwidget is super for such design.
        The widget it talks about is a page.
        so u get all the pages u want and on each page,
        u can have all the widgets u like.

        Normally the page is a plain
        qwidget but u can use own page if u need but
        often there is no need.

        ps. if you use UI files, you can visually manage all the pages. very handy.

        R Offline
        R Offline
        roseicollis
        wrote on 12 May 2016, 11:43 last edited by
        #3

        Hi @mrjj thank you for your reply. I'm really happy to know that QStackedWidget is the right way I have to take :D

        Now what I have is a QWizard that creates the QWizardpages with its behaviour:

        //QWizard .cpp constructor:
        WP1 *page1 = new WP1;
        setPage(Page1Mode, page1);
        
        // .h declaration
        enum {Page1Mode, Page2Mode, ...}
        

        So I imagine that now I need to have something like class MyStacked : public QStackedWidget and in its constructor something like:

        Page1Class *Page1 = new Page1Class();
        addWidget(Page1);
        

        am I right? So.. as this is my first contact with Qt I don't really know so much about it and its classes... you said: "Normally the page is a plain qwidget" ... So you mean that my pages will be something like class Page1: public QWidget ?? and there I can add my layouts and Qlabels and other QWidget as i had in my QWizardPages?

        Another thing? What about the tipical Next/Back buttons of the wizard configuration programs? As I said I don't need them all in every page so.. should I create them in every page of could I put them outside the QStackedWidget and make them general and just hide/ change their behaviour depending of the page shown?

        and a last question: With the wizard I could use the registerfield / set field functions to pass information between the QWizardPages so... how should I do it now ? Which will be the best method to avoid making global variables or a signal for every one? I'm talking that Page3 will need 5 different variables values from Page2 and other 6 differents from Page1 for example.

        Thank you!!!

        M 1 Reply Last reply 12 May 2016, 12:00
        0
        • R roseicollis
          12 May 2016, 11:43

          Hi @mrjj thank you for your reply. I'm really happy to know that QStackedWidget is the right way I have to take :D

          Now what I have is a QWizard that creates the QWizardpages with its behaviour:

          //QWizard .cpp constructor:
          WP1 *page1 = new WP1;
          setPage(Page1Mode, page1);
          
          // .h declaration
          enum {Page1Mode, Page2Mode, ...}
          

          So I imagine that now I need to have something like class MyStacked : public QStackedWidget and in its constructor something like:

          Page1Class *Page1 = new Page1Class();
          addWidget(Page1);
          

          am I right? So.. as this is my first contact with Qt I don't really know so much about it and its classes... you said: "Normally the page is a plain qwidget" ... So you mean that my pages will be something like class Page1: public QWidget ?? and there I can add my layouts and Qlabels and other QWidget as i had in my QWizardPages?

          Another thing? What about the tipical Next/Back buttons of the wizard configuration programs? As I said I don't need them all in every page so.. should I create them in every page of could I put them outside the QStackedWidget and make them general and just hide/ change their behaviour depending of the page shown?

          and a last question: With the wizard I could use the registerfield / set field functions to pass information between the QWizardPages so... how should I do it now ? Which will be the best method to avoid making global variables or a signal for every one? I'm talking that Page3 will need 5 different variables values from Page2 and other 6 differents from Page1 for example.

          Thank you!!!

          M Offline
          M Offline
          mrjj
          Lifetime Qt Champion
          wrote on 12 May 2016, 12:00 last edited by
          #4

          @roseicollis
          class MyStacked : public QStackedWidget
          That you only do if u need a subclass.
          else just use the base one.

          http://doc.qt.io/qt-5/qstackedwidget.html
          To insert u use
          http://doc.qt.io/qt-5/qstackedwidget.html#addWidget

          class Page1: public QWidget
          That you only need if u want a special page.
          Else u just
          new a QWidget and use for page. And add layout and stuff to it.
          You can use any widget as page.

          • Another thing? What about the tipical Next/Back buttons of the wizard configuration
            I would just put them outside and mainwindow controls the logic of next/prev and hide buttons.

          A more fancy version would be a custom composite control where it contains the logic inside but for 1 app. letting main handle it should be fine.

          -and a last question:
          I would have a Data class. and each page will save info to this class.
          So if page 5 read the data it will get what ever page 1 updated etc.
          No need to let the pages directly access each other.

          R 1 Reply Last reply 12 May 2016, 14:49
          0
          • M mrjj
            12 May 2016, 12:00

            @roseicollis
            class MyStacked : public QStackedWidget
            That you only do if u need a subclass.
            else just use the base one.

            http://doc.qt.io/qt-5/qstackedwidget.html
            To insert u use
            http://doc.qt.io/qt-5/qstackedwidget.html#addWidget

            class Page1: public QWidget
            That you only need if u want a special page.
            Else u just
            new a QWidget and use for page. And add layout and stuff to it.
            You can use any widget as page.

            • Another thing? What about the tipical Next/Back buttons of the wizard configuration
              I would just put them outside and mainwindow controls the logic of next/prev and hide buttons.

            A more fancy version would be a custom composite control where it contains the logic inside but for 1 app. letting main handle it should be fine.

            -and a last question:
            I would have a Data class. and each page will save info to this class.
            So if page 5 read the data it will get what ever page 1 updated etc.
            No need to let the pages directly access each other.

            R Offline
            R Offline
            roseicollis
            wrote on 12 May 2016, 14:49 last edited by
            #5

            @mrjj said:

            just use the base one.

            Then the base class of my app should be a QMainWindow where I create a QStackedWidget and add my QWidget pages or should I use another Base Class?

            class Page1: public QWidget
            That you only need if u want a special page. Else u just new a QWidget and use for page. And add layout and stuff to it.

            Yes but if I do it that means that if I need 30 pages I will have at least 30 layouts created with more than 100 different qwidgets all together which will be very ugly to see in code and difficult to understand to anyone that cames after me. So I think it will be better making a class for every page and create there all the QWidgets needed for that page... what do you think?

            M 1 Reply Last reply 12 May 2016, 14:54
            0
            • R roseicollis
              12 May 2016, 14:49

              @mrjj said:

              just use the base one.

              Then the base class of my app should be a QMainWindow where I create a QStackedWidget and add my QWidget pages or should I use another Base Class?

              class Page1: public QWidget
              That you only need if u want a special page. Else u just new a QWidget and use for page. And add layout and stuff to it.

              Yes but if I do it that means that if I need 30 pages I will have at least 30 layouts created with more than 100 different qwidgets all together which will be very ugly to see in code and difficult to understand to anyone that cames after me. So I think it will be better making a class for every page and create there all the QWidgets needed for that page... what do you think?

              M Offline
              M Offline
              mrjj
              Lifetime Qt Champion
              wrote on 12 May 2016, 14:54 last edited by
              #6

              @roseicollis
              Well if your application is of normal type then
              using QMainwindow as center seems good choice.
              You just place a QStacked in its UI and start adding pages.

              • 30 pages
                making a class for every page and create there all the QWidgets needed for that page... what do you think?

              Well I would add it all in UI file and there will be no need to see any of the code.

              But since I dont know how much processing each page does, its hard to say
              if your own sub class as page is better as u can then hook up signals etc internally.

              so depends on how much going on in each page.

              R 1 Reply Last reply 12 May 2016, 15:19
              1
              • M mrjj
                12 May 2016, 14:54

                @roseicollis
                Well if your application is of normal type then
                using QMainwindow as center seems good choice.
                You just place a QStacked in its UI and start adding pages.

                • 30 pages
                  making a class for every page and create there all the QWidgets needed for that page... what do you think?

                Well I would add it all in UI file and there will be no need to see any of the code.

                But since I dont know how much processing each page does, its hard to say
                if your own sub class as page is better as u can then hook up signals etc internally.

                so depends on how much going on in each page.

                R Offline
                R Offline
                roseicollis
                wrote on 12 May 2016, 15:19 last edited by
                #7

                @mrjj I understand... the thing is that every widget I use (layouts, labels, pushbuttons, combobox...) I create them by code like QLabel lab1 = new QLabel(); because it's faster for me and I prefer using its functions for position and height/width than just drag and drop on the ui file (which normally I have all in blank or I just don't have them). I'll think about if I should put it in the ui or in the code...

                One thing: I've created a new project to test that. The base clase of the project is QMainWindow so in its constructor I've write:

                    QStackedWidget *st = new QStackedWidget;
                    Page1 *page1 = new Page1;
                    st->addWidget(page1);
                
                    QVBoxLayout *layout = new QVBoxLayout;
                       layout->addWidget(st);
                       setLayout(layout);
                

                And then I've created a Page1 like this:

                //.h file:
                class Page1 : public QWidget
                {
                    Q_OBJECT
                public:
                    explicit Page1(QWidget *parent = 0);
                    ~Page1();
                private:
                    Ui::Page1 *ui;
                    QPushButton *_b1;
                    QPushButton *_b2;
                };
                
                //.cpp file, constructor:
                Page1::Page1(QWidget *parent) :
                    QWidget(parent),
                    ui(new Ui::Page1)
                {
                    ui->setupUi(this);
                   _b1 = new QPushButton;
                   _b2 = new QPushButton;
                
                   _b1->setText(QString::fromUtf8("AAAA"));
                   _b1->setMinimumSize(320,100);
                   _b1->setMaximumSize(320,100);
                
                   _b2->setText(QString::fromUtf8("BBBB"));
                   _b2->setMinimumSize(320,100);
                   _b2->setMaximumSize(320,100);
                
                   _b1->setVisible(true);
                   _b2->setVisible(true);
                }
                

                And when I run the program what I expect to see is a windows with 2 QPushButtons with texts AAAA and BBBB but instead of this what I get is 3 windows opened at the same time: One for MainWindow, One with the size of _b1 and just the this button and another with _b2 size and just this button on it....

                What am I missing here?

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on 12 May 2016, 15:24 last edited by
                  #8

                  @roseicollis said:
                  Hi
                  Code is also fine. But normally one use use layout so they can scale to mainwindow size and inserting into the UI directly works great. But letting the page new the widgets is also 100% valid and its mostly a matter of taste. (IMHO)

                  _b1 = new QPushButton;

                  There is a rule here u dont know. If you dont give a widget a parent it will automatically set window flag on it self and become a window :)
                  So _b1 = new QPushButton(this); will make them be inside the page.

                  R 1 Reply Last reply 12 May 2016, 15:51
                  0
                  • M mrjj
                    12 May 2016, 15:24

                    @roseicollis said:
                    Hi
                    Code is also fine. But normally one use use layout so they can scale to mainwindow size and inserting into the UI directly works great. But letting the page new the widgets is also 100% valid and its mostly a matter of taste. (IMHO)

                    _b1 = new QPushButton;

                    There is a rule here u dont know. If you dont give a widget a parent it will automatically set window flag on it self and become a window :)
                    So _b1 = new QPushButton(this); will make them be inside the page.

                    R Offline
                    R Offline
                    roseicollis
                    wrote on 12 May 2016, 15:51 last edited by roseicollis 5 Dec 2016, 15:51
                    #9

                    @mrjj said:

                    normally one use use layout so they can scale to mainwindow size and inserting into the UI directly works great.

                    Ok so you mean I should create the layout in the UI file? And it auto scale to mainwindow or should I do something else?

                    If you dont give a widget a parent it will automatically set window flag on it self and become a window :)

                    Mmmm interesting... I understand it but if I put (this) for both buttons now its right that I don't have their 2 new windows but I don't see them also in the MainWindow window so thinking about what you said before, I tried adding (this) to QStackedWidget *st = new QStackedWidget; and now I see something in the MainWindow which is _b2 .... any idea why I don't see _b1? And another thing:
                    I had to add a st->setMinimumSize(500,500);for my stacket widget... how could i tell him to take the parent's size, in this case MainWindow?

                    I'm understanding a lot of the Qt behaviour, thank you so much for your explanations @mrjj

                    M 1 Reply Last reply 12 May 2016, 16:01
                    0
                    • R roseicollis
                      12 May 2016, 15:51

                      @mrjj said:

                      normally one use use layout so they can scale to mainwindow size and inserting into the UI directly works great.

                      Ok so you mean I should create the layout in the UI file? And it auto scale to mainwindow or should I do something else?

                      If you dont give a widget a parent it will automatically set window flag on it self and become a window :)

                      Mmmm interesting... I understand it but if I put (this) for both buttons now its right that I don't have their 2 new windows but I don't see them also in the MainWindow window so thinking about what you said before, I tried adding (this) to QStackedWidget *st = new QStackedWidget; and now I see something in the MainWindow which is _b2 .... any idea why I don't see _b1? And another thing:
                      I had to add a st->setMinimumSize(500,500);for my stacket widget... how could i tell him to take the parent's size, in this case MainWindow?

                      I'm understanding a lot of the Qt behaviour, thank you so much for your explanations @mrjj

                      M Offline
                      M Offline
                      mrjj
                      Lifetime Qt Champion
                      wrote on 12 May 2016, 16:01 last edited by mrjj 5 Dec 2016, 16:58
                      #10

                      @roseicollis

                      • Ok so you mean I should create the layout in the UI file? And it auto scale to mainwindow or should I do something else?
                        No i just state the reason why using UI files often works as well as directly code and you
                        dont have to scroll around in all the "creation" code if handled by the UI.
                        --
                        I think ur b2 button is on top of b1
                        try b1->move(100,100)
                        --
                      • setMinimumSize(500,500);for my stacket widget... how could i tell him to take the parent's size, in this case MainWindow?

                      That what we use layouts for normally. It will scale all children to parent.
                      So in mainwin central u add widget , give it layout. then add Stacked to layout.
                      Now stacked follow main. Now u need to use layout in the pages so pages follow stacked that follow main. Sounds complicated but its not.
                      http://doc.qt.io/qt-5/examples-layouts.html

                      Will a sample help?

                      R 1 Reply Last reply 13 May 2016, 11:15
                      0
                      • M mrjj
                        12 May 2016, 16:01

                        @roseicollis

                        • Ok so you mean I should create the layout in the UI file? And it auto scale to mainwindow or should I do something else?
                          No i just state the reason why using UI files often works as well as directly code and you
                          dont have to scroll around in all the "creation" code if handled by the UI.
                          --
                          I think ur b2 button is on top of b1
                          try b1->move(100,100)
                          --
                        • setMinimumSize(500,500);for my stacket widget... how could i tell him to take the parent's size, in this case MainWindow?

                        That what we use layouts for normally. It will scale all children to parent.
                        So in mainwin central u add widget , give it layout. then add Stacked to layout.
                        Now stacked follow main. Now u need to use layout in the pages so pages follow stacked that follow main. Sounds complicated but its not.
                        http://doc.qt.io/qt-5/examples-layouts.html

                        Will a sample help?

                        R Offline
                        R Offline
                        roseicollis
                        wrote on 13 May 2016, 11:15 last edited by
                        #11

                        @mrjj said:

                        I think ur b2 button is on top of b1
                        try b1->move(100,100)

                        Totally right!

                        So in mainwin central u add widget , give it layout. then add Stacked to layout.
                        Now stacked follow main.

                        Isn't the same than what I already have? The difference I see is that you are adding first a widget to the mainwindow but I don't understand why...
                        My mainWindow code actually looks like:

                        MainWindow::MainWindow(QWidget *parent) :
                            QMainWindow(parent),
                            ui(new Ui::MainWindow)
                        {
                            ui->setupUi(this);
                            
                            QStackedWidget *st = new QStackedWidget(this);
                            st->setMinimumSize(800,800);
                        
                            Page1 *page1 = new Page1;
                            st->addWidget(page1);
                        
                            layout = new QVBoxLayout; //defined in .h file
                            layout->addWidget(st);
                            setLayout(layout);
                        }
                        

                        But then when I try to do layout()->addWidget(_b1); on Page1 and try to run the program it crashes at this point....

                        I've tried doing what you said, I think you mean this:

                            QWidget* centralWidget = new QWidget();
                            QVBoxLayout *layout = new QVBoxLayout;
                            layout->addWidget(st);
                            setCentralWidget(centralWidget);
                            centralWidget->setLayout(layout);
                            setFixedSize(600,600);
                        

                        But again the program crashes in Page1 constructor when I put layout()->addWidget(_b1); or parent-> layout()->addWidget(_b1);

                        1 Reply Last reply
                        0
                        • M Offline
                          M Offline
                          mrjj
                          Lifetime Qt Champion
                          wrote on 13 May 2016, 11:26 last edited by mrjj
                          #12

                          Hi
                          Main windows is a bit special since it has "central widget".
                          which there to allow to define areas around it
                          for Dock windows. That is why we insert widget first.
                          For all types of other widget we would insert directly.

                          QWidget* centralWidget = new QWidget();
                          QVBoxLayout *layout = new QVBoxLayout;
                          centralWidget->setLayout(layout);
                          layout->addWidget(st);
                          setCentralWidget(centralWidget);

                          seems fine.
                          For centralWidget , u can then use the Stacked.


                          My mainWindow code actually looks like:

                          MainWindow::MainWindow(QWidget *parent) :
                          QMainWindow(parent),
                          ui(new Ui::MainWindow)
                          {

                          setLayout(layout);
                          // that sets directly on mainwin. not sure it does what we think.

                          You can just single step and see the values to find out why u crash.
                          Sorry, i cant spot it. Running it helps.
                          I think u need a setCentral also.

                          That is the reason no 2 to why i like
                          UI file so much. no crashing as u can only insert legally when visually :)
                          And no code to try to spot bugs in.

                          I think u need
                          new widget
                          widget as central
                          new layout
                          layout to widget
                          inset stacked to that layout
                          and then the page stuff

                          1 Reply Last reply
                          0

                          6/12

                          12 May 2016, 14:54

                          • Login

                          • Login or register to search.
                          6 out of 12
                          • First post
                            6/12
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved