Switching app "states" using QMainWindow as superclass - c++

I'm attempting to run different modes/states of my app, for example having a menu which can go to a game state then highscore and from those two back to menu.
A solution I tried was using the autogenerated class QMainWindow as a superclass for creating the classes Menu and Game to start with. In QMainWindow I later want to create a QMainWindow, fill it with a Menu or Game and in eg. QMainWindow.paintEvents() call Menu.paintEvent() through polymophfism.
Now I know that I can't create a QMainWindow in another QMainWindow but would this idea work with yet another subclass called states or somthing inbetween the existing super/subclass(es)?
I was able to run just Game by itself (instead of QMainWindow) so the inheritance is probably done right. But when trying to create and run only a Game in QMainWindow it gave me a sigsegv at QMainWindow's constructor (which I have not changed and runs completely fine bby itself if empty). I've solved the problem with the classes including themselves in one another so that's not the problem either.

I solved it by making a superclass "State" for menu and game (without making State a subclass to QMainWindow) which is called by QMainWindow for each operation.
This is essentially the "states" pattern which I realise existed after the implementation.

Related

Preferred way to design application arhitecture in Qt

I have application which has MainWindow that is divided in three main parts:
Thing is, all three parts need to communicate between themselves. For example, there is a QListView in left section where you select items, and depending on the selected item options change in the right section.
I have come up with three solutions:
draw everything within the MainWindow which would make MainWindow one big superclass:
This solution solves all problems with communication between widgets because all of them are part of MainWindow::ui but then I get one big (potentially messy) class.
put each section in it's own class and make MainWindow a singleton:
This solution is... well a singleton. And I don't really like singletons. I will have access to MainWindow from everywhere (essentially I am creating a global variable) and I would still have to expose MainWindow::ui (and ::uis of other sections) via getter which would mean that everything will have access to ::uis.
put each section in it's own class and connect everything via signals and slots:
This would probably be the best solution but with this solution I need to create getter for each widget from EachSection::ui (to be able to connect it in MainWindow with it's counterparts), I would need a lot of calls to connect() and I also have a problem if two slots react to same signal but they need to react in specific order.
So what would be the best approach?
The best approach would be to define messaging (protocol) between views, so that views is not tightly coupled (all views isolated and dont know about each other) one instance class (main window) know all three and connects them. Imagine a button line edit and label, when you press button label gets value of line edit, button implementation does not depend on lineedit implementation, lineedit does not depend on label and so on, all three classes can be extended or changed and it doesnot affect two other, so you can focus on one of them at the time.

need help in a Qt Creator C++ app using Open GL

I'm writing an app in Qt Creator, using C++. The eventual goal is to have control over an OpenGL window from within the Qt main winow.
Initialization is fine, both mainwindow and OpenGL window start up with no issues.
The mainwindow is subclassed from QMainwindow, the OpenGL window is subclassed from public QWindow, public QOpenGLFunctions.
Here's the crux of the problem. I want event handlers in mainwindow to have access to the OpenGLWindow. I can't seem to make that happen. I've gotten past a number of obstacles so at this point I have the following set-up;
In main.cpp, I declare the objects for both mainwindow and OpenGLWindow. I have the mainwindow mousepressed event handler in main.cpp. As is, all works fine. Both windows come up as they should, and the event handler code does exactly what I want it to do in the mainwindow, just print some text in a textbox.
In order to have access to the openglwindow from the event handler in main.cpp, I declare the OpenGLWindow object as global, outside of the main () main.cpp (is this bad technique?).
Everything compiles fine, but when I run it I get the error 'QPixmap: Must construct a QGuiApplication before a QPixmap'. I assume that this means that the system is not happy that I am creating the OpenGLWindow before the application object.
Is there a more elegant way to do this? Am I a few lines away from correct code, or does this need some major rearranging.
BTW - I am doing this in Windows 10. The main reason I have chosen Qt and OpenGL for this app is that I want it portable to Linux.

Custom class in qt creator

I'm new to Qt and fairly new to C++ but I need help with this issue.
I have a custom class called HybridStack and I want it to extend a QStackedWidget and a QMainWindow.
I want it to extend a QStackedWidget so that I can use as many pages as I need and I want it to extend a QMainWindow so that I could be able to make each page have it's own MenuBar with different content of menu for different page.
I want to add this custom class HybridStack to Qt Designer by
promoting it from a QStackedWidget.
Is this possible? If it is, can you brief me on how to do this? If it's not possible then what's an alternative? Most importantly, I need to use it in the Designer because I need to use qmake
You can't derive from both QStackedWidget and QMainWindow, because both of those are in turn derived from QWidget. If you did so, you'd end up with the Dreaded Diamond. You'll have to use composition instead.
Even then, I'm not sure if it would work correctly to put a QMainWindow within a QStackedWidget, since it is designed to be a top-level item (i.e. its shown directly as a window, not embedded within another QWidget). Another way of accomplishing what you want (menu bar changing when the you change tabs) would be the following:
Make your top-level item a QMainWindow
Make the central widget a custom widget derived from QStackedWidget
When the item showing in the stack widget changes, you can call QMainWindow::setMenuBar to change the menu bar. Each widget within the QStackWidget could have its own QMenuBar instance that it uses for this purpose.

How to call QMessageBox Static API outside of a QWidget Sub-Class

I have a utility class in my Qt GUI application. However, in my convenience class I wanted to call a QMessageBox::critical(), warning(), etc. The class isn't a QWidget, and therefore I cannot pass this as the parent. My class is subclassed from QObject, however, so it can run things such as signals and slots. So to work around this--if it's possible to--should I maybe look at the property API instead of using the Static API?
Class declaration:
class NetworkManager : public QObject
And here's an example of a Static API call that fails:
QMessageBox::critical(this, tr("Network"), tr("Unable to connect to host.\n"),
QMessageBox::Ok | QMessageBox::Discard);
So, if I were to build a Property based API message box, would it be possible to call it in a QObject somehow? I haven't really used the Property Based API, but I understand from the documentation that it seems to use an event loop (i.e. exec()).
Just pass NULL for the first parameter:
QMessageBox::critical(NULL, QObject::tr("Error"), QObject::tr("..."));
A better way than passing nullptr is to use the qobject tree you are already using (assuming that the parent of the NetworkManager instance is a QWidget; adjust the number of parents according to whatever your qobject tree looks like)
QMessageBox::critical(qobject_cast<QWidget *> (parent()), "Title", "Message");
We use a qobject_cast<> instead of a C or C++ style cast is because it adds a little protection and will return 0 if it can't cast upward to the QWidget *.
If you use nullptr the QMessageBox will appear as centered over the topmost window (QWidget) rather than the window that actually appeared higher up in the qobject tree of your NetworkManager class. This really annoys people who have multiple monitors, lots of windows open, multiple windows from a single application spanning multiple monitors, etc.

Multiple QMainWindow instances?

The QMainWindow is the main window in a Qt application. So usually you'd have only one, but would it be possible at all to have multiple QMainWindow instances in your application?
I am working on integrating a Qt-based GUI application B into another Qt-based GUI application A. Both these applications have a QMainWindow, and I was considering as a first step to create a new QMainWindow that has both old QMainWindows on tabs. That way it would allow me to concentrate on wiring the backend of GUI B to the backend of A without having to change anything in the user interface itself. Is this a viable approach, or do you have other suggestions?
You can have as many QMainWindow instances as you want. A QMainWindow is just a QWidget which provides a menu bar, toolbar, status bar and docking framework. But basically it is just a QWidget so you can have as many as you like.
Normally you only have a single QMainWindow for GUI design reasons since it can be confusing to have multiple main windows. However, when implementing applications like QtAssistant which can open a new instance of themselves then the one process has multiple main windows.
What you suggest should work. The window with the tabs would not need to be a QMainWindow unless you want to also want add a toolbar to that window as well.