I have a fairly complex MVC structured application and I want a convenient way to update a QStatusBar from almost any part of it. My understanding is that I would have to pass around a lot of references to my QStatusBar or set up a bunch of signals in my controllers. It would get messy.
I also understand that QApplication is essentially a singleton. Would it be an acceptable idea to add a slot to it so that I could get the instance of QApplication from anywhere and emit to it?
Alternatively, what is a reasonable way to communicate global-ish things in my application without littering the controllers and views with references to widgets parented elsewhere?
How about implement singleton, that allow communication between components and gui, something like:
#include <statuscontroller.h>
StatusController::instance()->setStatus("Status string");
In this case only StatusController contain pointer to QStatusBar and available globally in gui thread.
With QObject as base class for StatusController you could use signals and slots.
Related
I'm quite a beginner in QtQuick, and I'm working on a small project where I have a C++ class (that I intend to register as a QML Type later) that, everytime my QML app feeds it some input, produce a QBitArray which gets read by QML and is outputted as a grid. (Basically, let's say I'm working on a 2D game with a board, where every cell has two possible states, and the list of states is produced by C++)
I'm wondering about the best way to make QML reads the BitArray. The most obvious solution to me would be to set it as a property, but QBitArray isn't a QObject (I guess I could inherit it and Qobject in a wrapper, but it feels unelegant).
I could also call a method of MyCLass wrapping the BitArray, but I'm wondering about threading overhead. If my object has been created in QML/JS, will there be overhead to call its C++ methods ?
So, in conclusion, what is the most elegant/efficient/idiomatic way to do this ?
A typical line I often need is
connect(thread, SIGNAL(started()), this->actExecute, SLOT(setDisabled(>>bool<<)));
But afaik you can't connect signals/slots with different signatures.
It's often recommended to use a helper method to trigger/emit a custom signal which passes true/false, but I have a lot of actions which needs to get disabled/enabled on thread start/stop/other, so I want to avoid writing dozens of helper functions/signals.
Is there a better way (maybe a single-line solution)?
There is a way to do this but it depends on Qt 5 and C++11. You can use a lambda expression to call the slot with the appropriate parameters. There was recently a question asking how to do this specifically with QTimers, here is a link to the answer I gave earlier.
Basically though, the code will look something like this-
connect(thread, &QThread::started, this->actExecute, [=]() {
setDisabled(true);
} );
Make your own Action class by deriving it from QAction and add simple disable() and enable() slots to it.
If Qt 5 and C++11 can't be used, there are 2 possible solutions for this problem:
1) Derive QAction
Derive QAction and add 2 simple slots(disabled/enabled) to it as #Roku said.
2) Derive QThread
Derive QThread and add an additional signal started(bool) which will be emitted with a true parameter when started() signal is emitted and with a false parameter when finished() or terminated() signals are emitted although I must note that being notified by a started(false) signal that the thread has finished is not that intuitive especially if you're developing an API that will be used by other people.
If both approaches make you change a lot of code, then I would recommend using helper methods instead. Beside these, I don't think you have a better alternative.
I have learned the basics of Qt and now interested in the depths of that pretty library. Please help me to understand:
Are the all classes derived from QObject?
Why is it possible to paint on a QWidget (and derived classes)?
What does the line return app.exec(); mean? What does exec() method do?
Are there virtual slots? And virtual signals?
Thanks.
All classes that need Qt's object model (e.g. by using signals and slots) must derive from QObject.
So that you can implement your own widgets, with a customised look. Any sensible GUI library would let you do that.
As documented, it enters the Qt event loop.
Slots can be virtual. Since signals do not have implementation (or rather, moc generates their implementation), they cannot be made virtual.
Qt has really good and extensive documentation, if you have more questions then they are probably already answered there. Start with Programming with Qt section.
To get a list of all the QWidgets created in an application we can simply call QApplication::allWidgets().
I've read the documentation, and I haven't found anything like this to get a list of all QObjects. If an application creates stand-alone QObjects that are not QWidgets I have no such function to use.
Is there a method to obtain such a list?
To begin with it's important to understand the difference between the QObject and QWidget classes.
class QObject
QObject instances have a pointer to their parent which may or may not be a null pointer. It's quite legitimate to create a QObject instance without a parent so long as you understand that it is your responsibility for that instance's lifetime i.e. if you don't delete it you will leak memory.
class QWidget
Although it appears you can create a QWidget without a parent, you can't. When you create an instance of a QWidget "without a parent" (i.e. by supplying a null pointer or letting it default to a null pointer) it's parent effectively gets set to your application's QApplication1 instance.
Is there a method to obtain such a list?
No. The reason QApplication::allWidgets() works is due to the fact that all QWidget instances have a pointer to them which is stored in your single QApplication instance. There is no central store of QObject pointers and therefore no in-built way of retrieving them.
One way around this is to ensure yourself that all QObjects instances (or instances of classes which inherit QObject) have a valid parent. Then you can use the QObject functions children(), findChild() and findChildren() to get pointers to these objects.
These are powerful tools, and like anything powerful, use them with care! Make sure you understand C++ object life spans before you use these in production code.
Notes:
QApplication inherits from QCoreApplication which inherits from QObject. There are some restrictions placed on how QApplication is used by the Qt framework.
I always try to apply the S.O.L.I.D principles and I really like the Qt toolkit but I find myself stuggeling all the time with the single inheritance rule.
If you are using multiple inheritance,
moc assumes that the first inherited
class is a subclass of QObject.
Also, be sure that only the first inherited class is a QObject.
How do you combine the single inheritance from a QObject rule and the Interface Segregation Principle.
I want to define the interfaces with signals and slots, but I'm not allowed to do this.
How do you get around this shortcomming?
Keep in mind that signals and slots are nothing more than functions that have special behaviors. Thus, you can use them to create interfaces.
For a full description of the process and a complete workaround for complex cases, see Qt Quarterly #15.
I don't think you can easily get around that with Qt's signal/slot mechanisms. You could try looking at either boost::signals or the sigc library, which are both more flexible in where you can place signals and slots. Be aware of possible namespace collisions with either library and Qt's signals and slots macros.