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. How to change QWizard default buttons in each QWizardPage

How to change QWizard default buttons in each QWizardPage

Scheduled Pinned Locked Moved Solved General and Desktop
qt4.8.5qwizardqwizardpagebutton custom s
16 Posts 3 Posters 8.7k 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.
  • J Offline
    J Offline
    jsulm
    Lifetime Qt Champion
    wrote on 18 Dec 2015, 09:36 last edited by jsulm
    #3

    What do you want to achieve with this code:

    void BaseWizard::ChangeButtons()
    {
        QList<QWizard::WizardButton> button_layout;
        button_layout <<QWizard::Stretch << QWizard::CustomButton1 << QWizard::CustomButton2;
     }
    

    You create a local variable button_layout which is destroyed when ChangeButtons() finishes!
    Shouldn't you call setButtonLayout(button_layout):

    void BaseWizard::ChangeButtons()
    {
        QList<QWizard::WizardButton> button_layout;
        button_layout <<QWizard::Stretch << QWizard::CustomButton1 << QWizard::CustomButton2;
        setButtonLayout(button_layout)
     }
    

    https://forum.qt.io/topic/113070/qt-code-of-conduct

    R 1 Reply Last reply 18 Dec 2015, 10:08
    0
    • J jsulm
      18 Dec 2015, 09:36

      What do you want to achieve with this code:

      void BaseWizard::ChangeButtons()
      {
          QList<QWizard::WizardButton> button_layout;
          button_layout <<QWizard::Stretch << QWizard::CustomButton1 << QWizard::CustomButton2;
       }
      

      You create a local variable button_layout which is destroyed when ChangeButtons() finishes!
      Shouldn't you call setButtonLayout(button_layout):

      void BaseWizard::ChangeButtons()
      {
          QList<QWizard::WizardButton> button_layout;
          button_layout <<QWizard::Stretch << QWizard::CustomButton1 << QWizard::CustomButton2;
          setButtonLayout(button_layout)
       }
      
      R Offline
      R Offline
      roseicollis
      wrote on 18 Dec 2015, 10:08 last edited by
      #4

      @jsulm O.o ermmmm... wow! yes, I used that function on the constructor the first time I create the buttons_layout but forgot it there in the function .... what a Stupid mistake... BUT now, putting it like you said it makes my program crashes.

          QList<QWizard::WizardButton> button_layout;
          button_layout.clear();
          qDebug() << " 1";
          button_layout <<QWizard::Stretch << QWizard::CustomButton1 << QWizard::CustomButton2 << QWizard::NextButton << QWizard::FinishButton;
          qDebug() << " 2 ";
          setButtonLayout(button_layout);
          qDebug() << " 3";
      

      If I run it with that code it prints 1 2 and then crashes in the setButtonLayout() function with a nice The program has unexpectedly finished.

      K 1 Reply Last reply 18 Dec 2015, 11:05
      0
      • J Offline
        J Offline
        jsulm
        Lifetime Qt Champion
        wrote on 18 Dec 2015, 10:13 last edited by
        #5

        Can you post the stack trace?

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        R 1 Reply Last reply 18 Dec 2015, 11:43
        0
        • R roseicollis
          18 Dec 2015, 10:08

          @jsulm O.o ermmmm... wow! yes, I used that function on the constructor the first time I create the buttons_layout but forgot it there in the function .... what a Stupid mistake... BUT now, putting it like you said it makes my program crashes.

              QList<QWizard::WizardButton> button_layout;
              button_layout.clear();
              qDebug() << " 1";
              button_layout <<QWizard::Stretch << QWizard::CustomButton1 << QWizard::CustomButton2 << QWizard::NextButton << QWizard::FinishButton;
              qDebug() << " 2 ";
              setButtonLayout(button_layout);
              qDebug() << " 3";
          

          If I run it with that code it prints 1 2 and then crashes in the setButtonLayout() function with a nice The program has unexpectedly finished.

          K Offline
          K Offline
          kshegunov
          Moderators
          wrote on 18 Dec 2015, 11:05 last edited by
          #6

          @roseicollis

          BaseWizard *bz;
          bz->ChangeButtons();
          

          Is this exactly how you use your wizard? If that's the case bz is just a wild pointer and doesn't actually reference any object.

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply
          1
          • J jsulm
            18 Dec 2015, 10:13

            Can you post the stack trace?

            R Offline
            R Offline
            roseicollis
            wrote on 18 Dec 2015, 11:43 last edited by
            #7

            @jsulm said:

            stack trace?

            How can I get it?

            @kshegunov Well I put the funcion on my BaseWizard and was trying to call it from a QWizardPage like that thinking it was correct... how should I do it instead?

            K 1 Reply Last reply 18 Dec 2015, 11:49
            0
            • J Offline
              J Offline
              jsulm
              Lifetime Qt Champion
              wrote on 18 Dec 2015, 11:47 last edited by
              #8

              You should get it if you execute your app from QtCreator and it crashes.

              You did not initialize the pointer, so it is showing to nirvana:

              BaseWizard *bz;
              bz->ChangeButtons();
              

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              R 1 Reply Last reply 18 Dec 2015, 12:00
              0
              • R roseicollis
                18 Dec 2015, 11:43

                @jsulm said:

                stack trace?

                How can I get it?

                @kshegunov Well I put the funcion on my BaseWizard and was trying to call it from a QWizardPage like that thinking it was correct... how should I do it instead?

                K Offline
                K Offline
                kshegunov
                Moderators
                wrote on 18 Dec 2015, 11:49 last edited by kshegunov
                #9

                @roseicollis
                Well, you have to operate on an object. If the way shown is the exact excerpt of the code you'll always get a segmentation fault, because in ChangeButtons() you dereference this by calling setButtonLayout(). You can use instead:

                BaseWizard * bz = dynamic_cast<BaseWizard *>(wizard());
                

                or any other way that actually provides you with the valid wizard object.

                Kind regards.

                Read and abide by the Qt Code of Conduct

                1 Reply Last reply
                0
                • J jsulm
                  18 Dec 2015, 11:47

                  You should get it if you execute your app from QtCreator and it crashes.

                  You did not initialize the pointer, so it is showing to nirvana:

                  BaseWizard *bz;
                  bz->ChangeButtons();
                  
                  R Offline
                  R Offline
                  roseicollis
                  wrote on 18 Dec 2015, 12:00 last edited by
                  #10

                  @jsulm Well in the Compile output it says that exit normally (if that is what you mean, if not, can you point me where can I find or see the stack trace?

                  @kshegunov said:

                  BaseWizard * bz = dynamic_cast<BaseWizard *>(wizard());

                  Annd.... DING DING DING! We have a winner here! Yes, this absollutely solves my problem. Thank you so much! I love a little with all that about casts... why can't you just do something like BaseWizard *bz = new BaseWizard() ? why do you have to use a cast and moreover, dynamic_cast ?

                  K 1 Reply Last reply 18 Dec 2015, 12:07
                  0
                  • R roseicollis
                    18 Dec 2015, 12:00

                    @jsulm Well in the Compile output it says that exit normally (if that is what you mean, if not, can you point me where can I find or see the stack trace?

                    @kshegunov said:

                    BaseWizard * bz = dynamic_cast<BaseWizard *>(wizard());

                    Annd.... DING DING DING! We have a winner here! Yes, this absollutely solves my problem. Thank you so much! I love a little with all that about casts... why can't you just do something like BaseWizard *bz = new BaseWizard() ? why do you have to use a cast and moreover, dynamic_cast ?

                    K Offline
                    K Offline
                    kshegunov
                    Moderators
                    wrote on 18 Dec 2015, 12:07 last edited by kshegunov
                    #11

                    @roseicollis
                    Firstly you'll need the wizard your page belongs to, this is the one you're trying to modify, that's why I suggested using the wizard() method. But that method (naturally) gives you a pointer to the base class (QWizard). Because you're trying to typecast a pointer down in the hierarchy and not up (which is always safe) your best bet is to do that with dynamic_cast. This ensures that if the object you receive is not from that hierarchy branch, or you pass a NULL pointer as argument, or your object can't be cast downwards (meaning that it actually is a base class object), the cast will return NULL. This provides you with a safe way to cast object pointers. The most clean approach is to use qobject_cast which works pretty much the same way, but for that you need your class to be declared as a metatype to Qt, which I was not sure you had done.

                    Kind regards.

                    Read and abide by the Qt Code of Conduct

                    R 1 Reply Last reply 21 Dec 2015, 10:36
                    0
                    • K kshegunov
                      18 Dec 2015, 12:07

                      @roseicollis
                      Firstly you'll need the wizard your page belongs to, this is the one you're trying to modify, that's why I suggested using the wizard() method. But that method (naturally) gives you a pointer to the base class (QWizard). Because you're trying to typecast a pointer down in the hierarchy and not up (which is always safe) your best bet is to do that with dynamic_cast. This ensures that if the object you receive is not from that hierarchy branch, or you pass a NULL pointer as argument, or your object can't be cast downwards (meaning that it actually is a base class object), the cast will return NULL. This provides you with a safe way to cast object pointers. The most clean approach is to use qobject_cast which works pretty much the same way, but for that you need your class to be declared as a metatype to Qt, which I was not sure you had done.

                      Kind regards.

                      R Offline
                      R Offline
                      roseicollis
                      wrote on 21 Dec 2015, 10:36 last edited by roseicollis
                      #12

                      @kshegunov

                      but for that you need your class to be declared as a metatype to Qt, which I was not sure you had done.

                      Neither do I :PWhat do you mean with metatype and how do you declare it? I just use to code making it works and if it does not, then I search on the internet and try to learn what it does but all that you mentioned its far away from my knowlegde...but I want to learn it all so that's why I ask it :) Thank you so much!

                      One more thing: I have my BaseWizard class like that:

                        #include "WPn"// include of all the wizardpages I have   (in the .cpp)
                        class BaseWizard : public QWizard
                      

                      And the BasePAge like this:

                         #include "basewizard.h" //(in the .cpp)
                         class BasePage : public QWizardPage
                      

                      And every QWizardPage like this:

                        #include "basewizard.h" // in .cpp
                        #include "basepage.h"   // in .cpp
                        class WP1 : public BasePage
                      

                      So now I'm trying to call in basewizard's constructor a function from basepage, but still have the same problem and don't know how to do it really, I've tried with something like:

                            BasePage *bp = dynamic_cast<BasePage *>( new QWizardPage()); // really not sure how to writte it sorry)
                            bp->SetSubTitleStyle();
                      

                      I know that as basewizard is not including basepage it is not possible (and I can't include it because its BaseWizard the one included on BasePage. So...How could I do that?

                      I need that because when you use setStyleSheet() on QT, it keeps the last one, it doesn't merge them or something like that so I have a general css for labels set in BaseWizard and I want one label (common in all wp) to have another style. I've also tried putting the Wizard style on basepage instead of basewizard but then the program crashes.. I do it putting that in the constructor of basepage:

                      BaseWizard * bz = dynamic_cast<BaseWizard *>(wizard());
                      bz->setStyleSheet("QWizard{background-color: black);}"
                                        "QComboBox:focus, QLineEdit:focus{ background-color: #dddddd; }"
                                        "QPushButton{ font-weight: bold; }"
                                        "QPushButton:focus{background-color: #8888a8); color:orange;}"
                                        "QLabel{font-weight: bold;color:orange}");
                      
                          SetSubTitleStyle(); //function that chagnes the common label css
                      
                      K 1 Reply Last reply 21 Dec 2015, 18:24
                      0
                      • R roseicollis
                        21 Dec 2015, 10:36

                        @kshegunov

                        but for that you need your class to be declared as a metatype to Qt, which I was not sure you had done.

                        Neither do I :PWhat do you mean with metatype and how do you declare it? I just use to code making it works and if it does not, then I search on the internet and try to learn what it does but all that you mentioned its far away from my knowlegde...but I want to learn it all so that's why I ask it :) Thank you so much!

                        One more thing: I have my BaseWizard class like that:

                          #include "WPn"// include of all the wizardpages I have   (in the .cpp)
                          class BaseWizard : public QWizard
                        

                        And the BasePAge like this:

                           #include "basewizard.h" //(in the .cpp)
                           class BasePage : public QWizardPage
                        

                        And every QWizardPage like this:

                          #include "basewizard.h" // in .cpp
                          #include "basepage.h"   // in .cpp
                          class WP1 : public BasePage
                        

                        So now I'm trying to call in basewizard's constructor a function from basepage, but still have the same problem and don't know how to do it really, I've tried with something like:

                              BasePage *bp = dynamic_cast<BasePage *>( new QWizardPage()); // really not sure how to writte it sorry)
                              bp->SetSubTitleStyle();
                        

                        I know that as basewizard is not including basepage it is not possible (and I can't include it because its BaseWizard the one included on BasePage. So...How could I do that?

                        I need that because when you use setStyleSheet() on QT, it keeps the last one, it doesn't merge them or something like that so I have a general css for labels set in BaseWizard and I want one label (common in all wp) to have another style. I've also tried putting the Wizard style on basepage instead of basewizard but then the program crashes.. I do it putting that in the constructor of basepage:

                        BaseWizard * bz = dynamic_cast<BaseWizard *>(wizard());
                        bz->setStyleSheet("QWizard{background-color: black);}"
                                          "QComboBox:focus, QLineEdit:focus{ background-color: #dddddd; }"
                                          "QPushButton{ font-weight: bold; }"
                                          "QPushButton:focus{background-color: #8888a8); color:orange;}"
                                          "QLabel{font-weight: bold;color:orange}");
                        
                            SetSubTitleStyle(); //function that chagnes the common label css
                        
                        K Offline
                        K Offline
                        kshegunov
                        Moderators
                        wrote on 21 Dec 2015, 18:24 last edited by kshegunov
                        #13

                        @roseicollis said:

                        What do you mean with metatype and how do you declare it?

                        A meta-type is a class/type that is known to Qt's meta-object system. You're required to declare your class as a meta-type when you intent to use Qt's template functions that depend on it (these include QVariant's conversions and qobject_cast). You also need to register your class at runtime as a meta-type if it will be used as an argument for queued signal-slot connections, which is relevant to multithreaded applications.

                        On your other question:

                            BasePage *bp = dynamic_cast<BasePage *>( new QWizardPage()); // really not sure how to writte it sorry)
                            bp->SetSubTitleStyle();
                        

                        This is a bad idea, because of two things:

                        1. Your wizard is managing your pages, but should not be required to know anything about how the pages are built or styled. This is a responsibility of your page, not your wizard.
                        2. The code is simply wrong, from C++ point of view. You create an object of type QWizardPage, then you try to cast the pointer returned to a derived class pointer, which will always cause dynamic_cast to return NULL (simply because QWizardPage is not a BasePage). So at the end of the day, when you call your function, you'll just get a segmentation fault because bp is NULL.

                        Suppose you have the following hierarchy:

                        class A { };
                        class B : public A  {};
                        class C : public A  {};
                        class D : public B  {};
                        

                        This means B is A, C is A, D is B (but because B is A, D is A as well). What you're trying to tell the compiler with your code is: "I have an object of type A and want to treat it (the dynamic_cast) as an object of type B", but you see, this is not correct, because while B is A, A is not B, so the dynamic_cast will always return NULL (meaning it can't provide a meaningful conversion). Now suppose you have objects created like this:

                        A * a = new A;   // This is okay, our pointer references object of the same type
                        A * b = new B;   // This is okay as well, our pointer references an object of type B (but threats it as an object of type A). It's possible because B extends A.
                        B * bb = new A; // Error! The object is of type A, and cannot be meaningfully accessed like it was of type B. B does not extend A, it's the other way around!
                        

                        So...How could I do that?

                        You could set your style for the page in the page's constructor (not in the wizard's constructor).

                        I hope this helps.
                        Kind regards.

                        Read and abide by the Qt Code of Conduct

                        R 1 Reply Last reply 22 Dec 2015, 14:30
                        1
                        • K kshegunov
                          21 Dec 2015, 18:24

                          @roseicollis said:

                          What do you mean with metatype and how do you declare it?

                          A meta-type is a class/type that is known to Qt's meta-object system. You're required to declare your class as a meta-type when you intent to use Qt's template functions that depend on it (these include QVariant's conversions and qobject_cast). You also need to register your class at runtime as a meta-type if it will be used as an argument for queued signal-slot connections, which is relevant to multithreaded applications.

                          On your other question:

                              BasePage *bp = dynamic_cast<BasePage *>( new QWizardPage()); // really not sure how to writte it sorry)
                              bp->SetSubTitleStyle();
                          

                          This is a bad idea, because of two things:

                          1. Your wizard is managing your pages, but should not be required to know anything about how the pages are built or styled. This is a responsibility of your page, not your wizard.
                          2. The code is simply wrong, from C++ point of view. You create an object of type QWizardPage, then you try to cast the pointer returned to a derived class pointer, which will always cause dynamic_cast to return NULL (simply because QWizardPage is not a BasePage). So at the end of the day, when you call your function, you'll just get a segmentation fault because bp is NULL.

                          Suppose you have the following hierarchy:

                          class A { };
                          class B : public A  {};
                          class C : public A  {};
                          class D : public B  {};
                          

                          This means B is A, C is A, D is B (but because B is A, D is A as well). What you're trying to tell the compiler with your code is: "I have an object of type A and want to treat it (the dynamic_cast) as an object of type B", but you see, this is not correct, because while B is A, A is not B, so the dynamic_cast will always return NULL (meaning it can't provide a meaningful conversion). Now suppose you have objects created like this:

                          A * a = new A;   // This is okay, our pointer references object of the same type
                          A * b = new B;   // This is okay as well, our pointer references an object of type B (but threats it as an object of type A). It's possible because B extends A.
                          B * bb = new A; // Error! The object is of type A, and cannot be meaningfully accessed like it was of type B. B does not extend A, it's the other way around!
                          

                          So...How could I do that?

                          You could set your style for the page in the page's constructor (not in the wizard's constructor).

                          I hope this helps.
                          Kind regards.

                          R Offline
                          R Offline
                          roseicollis
                          wrote on 22 Dec 2015, 14:30 last edited by
                          #14

                          @kshegunov Ohhh I see it now, I understand it so much better. Thank you for the explanation and the examples, they helped me a lot as they are easy to understand for me :). I know I can do it in every WP constructor but I wanted to avoid it as it mean I will have this line in every of my 50 wizardpages so that's why I was trying to set it in another way but seeing it is totally 'ilegal' then I'll do it this way.

                          Really greatfull for your reply! :D

                          K 1 Reply Last reply 22 Dec 2015, 20:19
                          0
                          • R roseicollis
                            22 Dec 2015, 14:30

                            @kshegunov Ohhh I see it now, I understand it so much better. Thank you for the explanation and the examples, they helped me a lot as they are easy to understand for me :). I know I can do it in every WP constructor but I wanted to avoid it as it mean I will have this line in every of my 50 wizardpages so that's why I was trying to set it in another way but seeing it is totally 'ilegal' then I'll do it this way.

                            Really greatfull for your reply! :D

                            K Offline
                            K Offline
                            kshegunov
                            Moderators
                            wrote on 22 Dec 2015, 20:19 last edited by
                            #15

                            @roseicollis
                            You're welcome.

                            I know I can do it in every WP constructor but I wanted to avoid it as it mean I will have this line in every of my 50 wizardpages so that's why I was trying to set it in another way but seeing it is totally 'ilegal' then I'll do it this way.

                            Well this is exactly why you have a BasePage class, isn't it? You put all the common functionality inside your base class (this would be your BasePage constructor) and when a wizard page is supposed to do something different you derive from your BasePage a new type that will provide you with the new behavior. My point is that your Wizard should not know about how the page is built or styled, but all the pages are of type BasePage, and BasePage does and should handle all the common things related to the wizard pages, while the wizard itself just collects and displays the pages.

                            Kind regards.

                            Read and abide by the Qt Code of Conduct

                            R 1 Reply Last reply 23 Dec 2015, 16:08
                            0
                            • K kshegunov
                              22 Dec 2015, 20:19

                              @roseicollis
                              You're welcome.

                              I know I can do it in every WP constructor but I wanted to avoid it as it mean I will have this line in every of my 50 wizardpages so that's why I was trying to set it in another way but seeing it is totally 'ilegal' then I'll do it this way.

                              Well this is exactly why you have a BasePage class, isn't it? You put all the common functionality inside your base class (this would be your BasePage constructor) and when a wizard page is supposed to do something different you derive from your BasePage a new type that will provide you with the new behavior. My point is that your Wizard should not know about how the page is built or styled, but all the pages are of type BasePage, and BasePage does and should handle all the common things related to the wizard pages, while the wizard itself just collects and displays the pages.

                              Kind regards.

                              R Offline
                              R Offline
                              roseicollis
                              wrote on 23 Dec 2015, 16:08 last edited by
                              #16

                              @kshegunov Yes yes I understand you and that was what I was trying to achieve but dunno why it didn't work fine. finally it works correctly without having to call it every time in every constructor of every wizardpage. The label that was not ok with the stylesheet had a QPalette with the colour and then some css with setStyleSheet() so seems that both are incompatibles and doing that the setStyleSheet() function was ignored. I've removed the QPalette and now it works perfect.

                              Thanks for everything!

                              1 Reply Last reply
                              0

                              12/16

                              21 Dec 2015, 10:36

                              • Login

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