In my Qt applications I typically tend to write all slots within the MainWindow class.
I'm using many manipulation of QSliders, QTextEdits and lots of QFormLayouts whose values influence status of other widgets (QGLWidget typically), controlled from within my MainWindow.
I admit I hate to do connection manually on each and every object within specialized methods of my MainWindow, this results in more than 2000 lines of code but it is very practical as from MainWindow I can access the UI.
I cannot imagine large scale applications are relegating all the methods within the MainWindow.
Are there some hints from software engineering to structure Qt applications in some smarter way?
Related
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.
Since creating widgets takes a lot of time, I try to create widgets in different threads and add them to the main layout, but that fails. When creating widgets and then adding them sequentially, the program works normally. Notifications I received: "QObject::setParent: Cannot set parent, new parent is in a different thread"
Is there a way to do it?
No, there is no way to do it.
Qt GUI classes including QWidget must be used only from the main thread.
Quoting Qt documentation:
Although QObject is reentrant, the GUI classes, notably QWidget and
all its subclasses, are not reentrant. They can only be used from the
main thread. As noted earlier, QCoreApplication::exec() must also be
called from that thread.
This is enforced in Qt code by a Q_ASSERT_X when you construct a QWidget:
Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
"Widgets must be created in the GUI thread.");
So, even if you would find some work around to make it work, you would not have any guarantee that your code will work in a reproducible way and that any Qt update will not break your code.
Regarding your specific problem, creating widgets should not be time consuming. I can think of 2 reasons why it would be time consuming:
Your widgets are doing heavy computation when you create them. Then you shoul put the computation, and only the computation, in another thread.
You are creating a lot of widgets in one shot. The you can deffer the creation using the event loop. Basically, you create some widgets then post an event or set a timer that will create some more widget, etc. until you meet some stop conditions.
I am considering a rewrite of an MFC Dialog application I wrote over a decade ago. I originally chose a Dialog application type because in general the user clicks control inputs and the application provides real-time data from hardware via USB and displays the data in edit boxes. The app also writes information to a file. Since the user never does any file editing I didn't see a need for SDI or MDI application type.
I've now learned that the SDI application type along with CFormView provides some interesting advantages such as scrolling, window resizing:
http://forums.codeguru.com/showthread.php?267664-MFC-Dialog-How-to-enhance-a-dialog-based-application-with-Menu-Toolbar
The reason for my rewrite is that my application is un-maintainable and doesn't scale well. Originally I created a CDialog for each type of "screen" that I show but lots of code is common among the various screens. In fact over time I started reusing CDialog classes and with the use of state variables simply hid, renamed, or repositioned many of the controls to make the screen look appropriate in the context of the application.
I tried deriving the CDialog classes from a common base class but I didn't achieve great code reuse this way. I also found that I had common resources that I was constantly passing around to the various windows which just added unnecessary overhead.
As the application evolved it also became difficult to keep track of the state of the application (for processing USB hardware data input, user input, button enabling etc). Using a hierarchical statechart as the basis for my application might clean this up.
Should I consider putting a superset of ALL the necessary controls on ONE CFormView and simply hiding, renaming, and repositioning controls from the very beginning and using a statechart to manage this?
All the examples I see put the code directly in the input control handlers but maybe I should use the handlers to change state and then let the state machine do the decision-making to reduce this spaghetti code.
So my primary questions are:
1. Would SDI would buy me anything for writing and reading files (such as reporting and logging) if the user does not perform editing?
2. Does CFormView make sense?
3. Does it make sense to put all controls on one CFormView instead of multiple classes and Dialog resources?
4. Have you tried using a state machine in MFC such as Boost Statechart or Miro Samek's Quantum Leaps?
http://www.boost.org/doc/libs/1_58_0/libs/statechart/doc/index.html
http://www.state-machine.com/products/index.html
In my application the main window's GUI is designed in the Qt-Creator designer. I have had some trouble in getting it to look just the way I'd like, but I can when doing the GUI in C++ code.
So, I plan to change the application's main window to be laid out in code.
What should I keep in mind when doing this?
How do I make sure all the menu items and button clicks etc. get migrated, too?
In my Qt experience I almost always write layout in code and here is what I can suggest:
a) Spend some time thinking which Layout to use, personally I tend to use either QGridLayout or nested QHboxLayout and QVBoxLayout which give you lot of flexibility.
b) I normally declare all child widgets as class variables always pointers and I create the real objects in the Main windows constructor.
About not to forget any control I suggest to print the XML of the UI file and draw a line on each control you recreate in the code.
As a good starting point, simply copy-pase the setupUi method from the ui_xxx.h file that uic had generated for you. You can then manually edit the setup code to suit your needs.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Consider the case of a simple GUI displaying the output of rather elaborate calculation.
Now I would like to write a nice, custom GUI using QML.
I would also like to write my background app in QT C++.
I'm sitting in front of the QT documentation and wonder
if I
1) should write a QML application and somehow embed my C++ classes in it
(which is absolutely possible) or if I
2) should write a C++ application
and somehow embed the QML GUI in it and modify QML properties from my classes
(which is again possible)
I already wrote everything in C++ using QT Widgets for the GUI. I only want to move the GUI to QML and keep the C++ classes even though I am willing to rewrite the interface to the GUI.
Possible anser:
The marked solution below suggested keeping the C++ classes and interface the GUI exclusively through SIGNALS and SLOTS. So basically I ended up with a main.cpp that instantiates my main working class and displays the QML GUI like this:
QQuickView viewer;
viewer.setSource(QUrl("./qml/main.qml"));
viewer.show();
then I added myClass and got me an object to do the connections:
MyClass myClass;
QQuickItem* item = viewer.rootObject();
QObject::connect(item, SIGNAL(buttonClicked()), &myClass, SLOT(mySlot()));
QObject::connect(&myClass, SIGNAL(mySignal(QVariant)), item, SLOT(updateGUI(QVariant)));
When implementing the slots and signals in the C++ classes you must use QVariant objects to transfer the data. The QML file then implements SIGNALS e.g. for clicked buttons and SLOTS to receive data to display.
This is exactly what I was hoping for. The only change to my non GUI code was to do all the interactions via SIGNALS and SLOTS. Now I can even use both GUIs (QML / Widgets) for my application.
Just write your core logic in C++, interface it with signals and slots, and you can use the same component with widgets and also with QML.
It is not rocket science, C++ logic allows usage with C++ and QML, JS logic - only QML. C++ and the Qt API is the more sound solution, because from JS you don't really have access to that much functionality of the Qt APIs, only a few methods are "ported" into the QML world. But all the high performance data containers and the execution performance itself is in C++.
If you only need to display results and console is not good enough, I'd rather keep to QtWidgets, because adding the declarative module slows compilation down significantly. The widget module is standalone now, so you are adding "extra" module even with QtWidgets (in Qt4 it was part of QtGui) but it is lighter. After you use widgets for prototyping your core logic, you can then implement a QML interface and just hook that up to the existing signals/slots/properties and bindings using them.
And no, you don't embed QML in C++ classes, it is the other way around, C++ is the more low-level layer, which is used to create QML components. As for the actual instantiation, you can go both ways - if you register a QObject based class to the QML engine, you can instantiate it in QML. Or you could instantiate the class in C++ and only make it available in the QML context - it doesn't really matter. If you need a single object, you better instantiate it in C++ in the main() function and make it available in the QML context, if it is components you intend to instantiate a lot - then create a QML component.
You could prototype the core logic with JS in QML and later port it to C++ if you want too. It looks like twice the effort, but if you make your bed right it is actually a productivity increase, because prototyping is that much faster in QML, catching errors is much safer and informative, and if you make your API well, porting the JS code to C++ is usually a minor nuisance - replace some vars with concrete types, replace some . with -> and stuff like that.
Any "elaborate calculation" you really WANT to ultimately do in C++. Every time the calculation is completed, you can simply emit it as a signal, and automatically display the result to whatever slot the signal is connected, be that in a widget or in QML, or even both at the same time.
This is very opinion based. No 'true' answer possible. For me it is 'easier' to write in QML and 'extend' qml with Qt plugins. That's because I did a big project this way. Others might have other experiences and might because of that like a different approach. None of our 'life stories' could help you much.