PDA

View Full Version : Need a working example of promoting QWizardPage in Qt Designer



astodolski
25th October 2012, 20:14
I have been unsuccessful trying to promote QWizardPages created in Qt Designer. I can't seem to get pointed answers. Additionally this is something that is not well covered in any of the docs or any of the forums out there. Qt Designer creates as many of the pages needed. Any and all objects are only accessible from the ui object created in the one class associated with the project created.

I very much am in need of the simplest case that initially creates a multi page wizard in the designer and allows a class to promote one (or more) of a QWizardPage to.

Please help.

Thanks in advance.

wysota
25th October 2012, 20:43
I have been unsuccessful trying to promote QWizardPages created in Qt Designer. I can't seem to get pointed answers. Additionally this is something that is not well covered in any of the docs or any of the forums out there. Qt Designer creates as many of the pages needed. Any and all objects are only accessible from the ui object created in the one class associated with the project created.

I very much am in need of the simplest case that initially creates a multi page wizard in the designer and allows a class to promote one (or more) of a QWizardPage to.

Start Designer, choose QWizard, right click on the form (or in the object hierarchy pane on one of the pages), choose the page from the popup menu and choose "Promote". Enter desired data in the dialog, confirm and you're done.

astodolski
25th October 2012, 21:22
Start Designer, choose QWizard, right click on the form (or in the object hierarchy pane on one of the pages), choose the page from the popup menu and choose "Promote". Enter desired data in the dialog, confirm and you're done.

I know it should be that easy - especially in light of the steps you placed. However there's one thing that's unclear. Since I already have a app that is a Wizard with multiple pages in a ui file. All objects are referenced from there and the ui object gets created from the main class. If I add wizard page classes to the main wizard class header file, I then promote each page in designer to the class name I created and reference the same header file. It's the only one anyway. The files in the project are: wizard.cpp, wizard.h, ui_wizard.h, wizard.ui. These are what was created in Qt Creator new project "wizard".

wysota
25th October 2012, 21:58
I know it should be that easy - especially in light of the steps you placed. However there's one thing that's unclear. Since I already have a app that is a Wizard with multiple pages in a ui file. All objects are referenced from there and the ui object gets created from the main class. If I add wizard page classes to the main wizard class header file, I then promote each page in designer to the class name I created and reference the same header file. It's the only one anyway. The files in the project are: wizard.cpp, wizard.h, ui_wizard.h, wizard.ui. These are what was created in Qt Creator new project "wizard".

If you already have the pages, I don't see why you want to assemble the wizard in Designer again.

ChrisW67
26th October 2012, 00:28
Also see the answer in the antique thread you also reopened with this question.

astodolski
26th October 2012, 02:38
If you already have the pages, I don't see why you want to assemble the wizard in Designer again.
I need to re-implement functions of the individual pages and access any widgets placed in those pages. What's your suggestion to do that? The only other way I see to do that is to access them from the ui object defined in the base class. How does one observe modular designs? Do you put all code in one class? So, I hope I was clearer.

I approached wizard design by creating an app which contains QWizard as the main class. Five files are created: main.cpp, wizard.cpp, wizard.h ui_wizard.h, wizard.ui. The individual wizard pages are contained as objects from within the .ui file. I wanted to access those pages similar to the way the example wizards are designed in the examples of Qt distributions but my wizard is created in the designer.

I hope that is clearer.

Thanks for any help.

Added after 22 minutes:


Also see the answer in the antique thread you also reopened with this question.

Antique indeed. It's a unique issue, not getting a lot of attention on the Qt forums out there. I suppose most prefer to build interfaces solely in code rather than use the designer.

wysota
26th October 2012, 09:55
I need to re-implement functions of the individual pages and access any widgets placed in those pages.
You won't be able to do that from Designer. It's for making widgets layouts, not reimplementing classes.


What's your suggestion to do that?
Subclass or otherwise modify the class you wish to change.


I suppose most prefer to build interfaces solely in code rather than use the designer.
When it comes to QWizard, there is not much to gain from using Designer to assemble it. There are more benefits if you implement each page in Designer and then put them together in code.

astodolski
26th October 2012, 12:24
You won't be able to do that from Designer. It's for making widgets layouts, not reimplementing classes.


Subclass or otherwise modify the class you wish to change.


When it comes to QWizard, there is not much to gain from using Designer to assemble it. There are more benefits if you implement each page in Designer and then put them together in code.
It may be I'm not properly explaining my goal. I ONLY want to use designer to perform layout and re-implement objects of such a layout in code. It's not covered in either the docs or examples how users re-implemented page methods as you described.

wysota
26th October 2012, 14:03
It may be I'm not properly explaining my goal. I ONLY want to use designer to perform layout and re-implement objects of such a layout in code. It's not covered in either the docs or examples how users re-implemented page methods as you described.

I think you need to say what you mean by "re-implement objects" and "re-implemented page". Reimplement from where?

astodolski
27th October 2012, 01:49
I think you need to say what you mean by "re-implement objects" and "re-implemented page". Reimplement from where?
OK, if it will help get to a solution. Objects for a wizard are defined (.h) (.ui) and implemented (.cpp) in the code files that are created in the new project designer. Accessing is through the pointer to Ui::WizardClass. Any overrides or sub-classing or reimplementing is through promoting to new classes.

OK?

wysota
27th October 2012, 07:52
that are created in the new project designer.
Do you mean Qt Creator's new project wizard?


Accessing is through the pointer to Ui::WizardClass. Any overrides or sub-classing or reimplementing is through promoting to new classes.
You can't do that in Qt Designer. The latter operates on UI files only. If you already have C++ classes that you wish to change then subclass them or simply change them and adjust their UI incarnation by changing the promotion class in Designer.

Or maybe I just fail to see your problem.

astodolski
28th October 2012, 19:37
Do you mean Qt Creator's new project wizard?


You can't do that in Qt Designer. The latter operates on UI files only. If you already have C++ classes that you wish to change then subclass them or simply change them and adjust their UI incarnation by changing the promotion class in Designer.

Or maybe I just fail to see your problem.

No actually, I think we are getting closer to a solution, though I don't know why it doesn't appear clearer. I have for each page (two for now) as a promoted class. i.e. PageOne, PageTwo. They in turn have separate code and headers files created for them. I have to re-implement initializePage for each page. This is why I promoted the two. So to summarize, the point of already having classes I wish to change are only the two that I created by promoting in designer. All the main accessing of objects remains with the pointer to the Ui::Wizard class. I may not see any addition to this thread for a while as a monster storm approaches.

astodolski
1st November 2012, 20:09
Do you mean Qt Creator's new project wizard?


You can't do that in Qt Designer. The latter operates on UI files only. If you already have C++ classes that you wish to change then subclass them or simply change them and adjust their UI incarnation by changing the promotion class in Designer.

Can you elaborate on how to adjust their UI incarnation?

ChrisW67
1st November 2012, 21:56
In Designer you put a placeholder widget, generally of a similar type, in the space you want your custom widget to occupy. Then you tell Designer to "promote" that placeholder to another custom class. This has the effect of causing the UI compiler (uic) to generate code that creates (incarnates) the custom widget where it would otherwise have created the placeholder widget. From your description above you are already doing this. QWizard built this way would simply contain promoted placeholders for the pages.

Designer can be used to build the UI of the custom widget. This Designer UI is completely independent of any Designer UI that might eventually contain the custom widget. The implementation of the custom widget behaviours is done in C++ code not Designer.

astodolski
8th November 2012, 00:51
In Designer you put a placeholder widget, generally of a similar type, in the space you want your custom widget to occupy. Then you tell Designer to "promote" that placeholder to another custom class. This has the effect of causing the UI compiler (uic) to generate code that creates (incarnates) the custom widget where it would otherwise have created the placeholder widget. From your description above you are already doing this. QWizard built this way would simply contain promoted placeholders for the pages.

Designer can be used to build the UI of the custom widget. This Designer UI is completely independent of any Designer UI that might eventually contain the custom widget. The implementation of the custom widget behaviors is done in C++ code not Designer.
What's not clear then is how do you access objects created in the designer? That is, do you call it from the ui object or the objects created in the promoted classes? The promoted classes don't have scope into the ui object if you understand what I mean. I would have commented sooner but we just had a pretty bad hurricane hit us last week and now are in the middle of a snowy NorEaster.

wysota
8th November 2012, 04:55
All ui objects can be accessed through the wizard object (if you provide API for this of course) by casting the return value of QWizardPage::wizard() to your wizard class type. Furthermore you shouldn't need that since important fields can be registered by the wizard class and accessed from each page.

astodolski
14th November 2012, 19:49
All ui objects can be accessed through the wizard object (if you provide API for this of course) by casting the return value of QWizardPage::wizard() to your wizard class type. Furthermore you shouldn't need that since important fields can be registered by the wizard class and accessed from each page.

I'm sorry but that doesn't make sense to me. Let me explain. I have two pages in a wizard. I promoted both pages to their own separate classes. I now can override methods of each page like initializePage, nextId etc. So in PageOne::initializePage() I need to write to a label on that page. The only way to do that is by calling ui->labelOne which of course is not in scope. I am seeing that I have to promote each object in each page. But the alternate method you seem to suggest is to register those labels as a fields to be accessible. The question becomes accessible by the ui or by the promoted pages? Qt is quite a screwy paradigm for visual programming.

wysota
14th November 2012, 23:47
I'm sorry but that doesn't make sense to me.
Well... doing what you are doing doesn't make sense to me too.


Let me explain.
I understand what you are doing, there is nothing to explain.


So in PageOne::initializePage() I need to write to a label on that page. The only way to do that is by calling ui->labelOne which of course is not in scope.
No, that's not the only way. Your wizard is implemented as a subclass of QWizard that has the UI created in Designer applied on it. Therefore you can implement getters and setters for all the variables you need in this subclass. Or if you don't care about proper OOP, you can just make the wizard's "ui" member public instead of private.


But the alternate method you seem to suggest is to register those labels as a fields to be accessible. The question becomes accessible by the ui or by the promoted pages?
Both. See QWizard::field(). You just need to register all the fields first.

Qt is quite a screwy paradigm for visual programming.
No, you're just not using it in the way it was designed to be used.

astodolski
15th November 2012, 01:02
Well... doing what you are doing doesn't make sense to me too.


I understand what you are doing, there is nothing to explain.

You understand what I'm doing but it doesn't make sense? -- Hmm.

I admit I am not an expert in Qt. To the point of using it as designed. If you approach the designer to create a wizard with a number of pages, that is relatively easy to be successful. Works as designed. The other variants of creating wizards are just not well represented in the documentation or included examples. The other development environments by Microsoft and Borland share similar paradigms of creating graphical interfaces with code behind. Qt is very different.

Just trying to understand the way things work with Qt.

wysota
15th November 2012, 05:35
You understand what I'm doing but it doesn't make sense? -- Hmm.
Yes, exactly.


I admit I am not an expert in Qt.
Qt is not an issue here. Object oriented programming is. There is the object of the wizard that contains all the UI elements (as you chose to put them there in Designer). The wizard object also contains a number of page instances. Since the pages and UI elements are encapsulated in the wizard object, they are not aware of each other. One page can't access another page's items since it doesn't even know another page exists and it can't access the wizard's items since it doesn't know there is a wizard anywhere. In C++ (again, not anything related to Qt itself) you cannot inject code into existing classes therefore if you put some items in the wizard UI, its code cannot be injected into the classes you are externally creating. Again and again, this is nothing Qt-specific, it's simple object oriented programming.

If you really want to separate the logic of each page then do exactly that, extract the logic and not the page itself. Don't promote each page in Designer, instead create a couple of "algorithm" instances (working on the wizard class instance) in your wizard's constructor and when the wizard switches pages, assign the correct logic you want to be the "current" one. This way you follow both the "strategy" design pattern and the state machine paradigm. Both are standard, both are classic, no need to reinvent the wheel.



Qt is very different.
Qt follows object oriented programming paradigm. Borland is sh*t and M$ is always inventing its own "standards" that are incompatible with everyone else.

Just take a piece of paper and a pencil, draw each object and objects it encapsulates (which will visualize their access scope) and everything should become clear.