How to handle multiple "screens" on the GUI
-
Hi all,
I have a conceptual question. I want to make a GUI with multiple pages or screens. There would be kind of a menu from which you can open different screens. Each screen will have it's own functionality, events and logic implementation, but they also need to communicate between them.
I was thinking about using a Stacked Widget to switch between the screens, but the problem with this is that all of the events are still captured in the Main Window. This can easily become very messy as the number of screens increases.
To me this sounds like a typical object-oriented problem, where I would make a class "Screen", probably inherited / SubClassed from the QWidget or QFrame and then create instances for each screen and keep them in the Main Window. But then I don't know how to get these screens integrated with the designer and place them in the Main Window and all.
Sorry if the question is very basic, I'm trying to get a hang of the whole Qt thingy. Have to say I love it so far. The Qt Designer makes life so much easier.Thanks for the help.
-
If they are as separate as you say then I don't think you should integrate them into the main window in the designer. I think the main window doesn't need to know the particular subclasses of the your "screen" class. I would give it a generic
addScreen(Screen*)
function and then load them at runtime. This way you would design main window and each screen separately in the designer keeping them nice and separate.
As for the communication between screens - there are a lot of different designs, ranging from a crude "star design" based on a singleton to more sophisticated subscription, observer or mediator patterns. Which is best depends on your particular case and what kind of communication you have in mind. -
Hi
Thanks for the answer. This sounds like a good approach. However, this brings up a few further questions.
Assuming I design my sub-screens separately, is there a way to insert them into the main window in the designer just to see how it looks like combined?
Additionally, I am using the Style-Sheets to design the GUI. I made a quick test and found out that when the screen is inserted into the main window at run-time, it will be formatted by the Style-Sheet of the main window which is good, but how can I make this happen in the designer too? I want the screens to use the main window Style-Sheet already when designing them.
Well, the point is, keeping the screens separate is good in terms of organization and keeping the code clean, but I would also like to see the final result in the designer.Regarding the communication, can I kindly ask you to give me some reference material about these designs you mentioned? Well the communication I have in mind is fairly simple. User does some things in one screen, and when switching to another screen some of the data has to be passed to it.
Thank you.
-
is there a way to insert them into the main window in the designer just to see how it looks like combined?
There is... but it's so inconvenient I tend to say there isn't. You would have to create a designer plugin for each screen and use it in your main window. You can see the example but I'd say it's a lot more work and maintenance than it is worth. It's a lot less hassle to just compile and run the app.
I want the screens to use the main window Style-Sheet already when designing them.
Unless using the plugin approach I mentioned there's no way (that I know of) to do that. The stylesheets are propagated from a parent object and designer has no way to specify a parent object for top-level windows, as this is done at runtime in your c++ code.
My approach with this is that I don't really rely on the designer for the styles. I usually use it to design the general layout of things and then apply a stylesheet file from resources at runtime. You need to know that the designer has some kinks in regards to stylesheets and things don't always work the same at runtime as in the designer.
The stuff I mentioned you can find all over, e.g. on wikipedia. Just enter them into your favorite search engine.
For really basic communication a simple design like this could be enough (this is a rough pseudo-code obviously):struct SharedState { int foo; }; struct IPage { void setSharedState(SharedState* state) = 0; }; class FirstPage : public IPage { /* does some stuff with shared state */ }; class SecondPage : public IPage { /* does some other stuff with shared state */ }; class PageManager() { SharedState state; void addPage(IPage* page) { page->setSharedState(&state); mainWindow->addPage(page); } } ... pageManager->addPage(new FirstPage); pageManager->addPage(new SecondPage);
-
Thank you.
For the css I found out there is a Bug created in Jira for it. Someone posted a plugin in the comment which partially solves the problem, but unfortunately the link is not working, so I guess I will have to manually copy the css between the ui's. Guess I can live with that, but it's kind of weird that this is not a more common issue for developers.As for the logic, I have implemented something along these lines. I have a ScreenManager with instances of all subscreens, including the main frame. As soon as one subscreen needs another screen to be loaded, it emits a signal which is captured by the ScreenManager which handles the switching logic.
I am still not sure this is the right approach. Perhaps I should make it in a way that each screen has a reference to the ScreenManager and calls it's functions when a screen needs to be switched.
I guess I will see with time what is better, but the thing is it's better to make a good design at the beginning instead of re-designing later on. I feel like I should have payed more attention to the OOP lessons at the Uni. -
Hi
I have additional question. Maybe I should open a new topic, but it's kind of related.
So, I am making this GUI with the sub-pages. The thing is, the same GUI will be used for different customers. Some will have certain pages disabled and also logic of a single page might be slightly different. Some customers may have exactly the same GUI. The question is, should I inherit from a basic page for each customer and override certain functions, or should I have a single page and use a variable "Customer" and make certain exceptions with the if structures.
Additional thing bugging me is that some of the pages will look very similar and have a similar functionality. There might be some additional elements or some less. Again, should I use inheritance or a variable with the if structure?
I don't want to overuse the inheritance, but I imagine the if-structures can get messy, especially as the number of customers grows.
So, my idea was to do the following:- basicPage
- similarPage
- similarPageCustomer1
- similarPageCustomer2and3
- anotherSimilarPage
- anotherSimilarPageCustomer1
- anotherSimilarPageCustomer2and3
- thirdSimilarPage
- thirdSimilarPageCustomer1
- thirdSimilarPageCustomer2and3
- similarPage
But that seems like a lot of inheritance and new classes for each customer, considering that for some of them only minor things might be different, or nothing at all.
Thanks for the advice. - basicPage