In QWidget, rather than being signals, mouse and paint and other events are virtual functions to be overloaded. Why is this the case, rather than being consistent?
Although I can't find anything within Qt's documentation that states their motivations for using virtual functions for events, I can guess:
Signals and slots can be nice to work with, but there's overhead associated with them (see, the answer to this question). Since events are triggered quite frequently, the use of signals and slots could carry quite a performance penalty.
Some event handlers need to return values. Returning a value from a slot back to the signal emitter is not officially supported (though see this question), which means that they wouldn't be appropriate.
Signals emitted from QWidget may not make sense from a design point-of-view. If I create my own widget derived from QWidget, why have signals emitted from my widget that just connect back to slots within the widget itself? This also has the danger of breaking encapsulation since signals are always "public".
Even if none of the above were true, there would still be quite a few architectural questions raised by trying to use signals for events. For example, a single event is often passed to multiple different objects (for example, in the case where some objects don't wish to process the event). In this scenario, which object emits the signal indicating that the event has taken place? It's certainly not the target of the event (i.e., the widget, as you've implied above). It would have to be some other global object. But if that were true, we would likely just implement virtual slots on every widget to handle the signal. This essentially just gets us back to where we started with virtual functions!
Related
With Qt, I can filter all the QEvent events my application receives or produces with:
qApp.installEventFilter(my_filter_object)
Is there any way to filter Qt signals (of signals and slots) in a similar manner I can filter QEvent events?
With QtCore.QStateMachine.SignalEvent extending QEvent, and StateMachineSignal QEvent.Type being there, everything seems to be in place, but my event filter can't seem to catch one of these.
IOW, is there any way to get the signal's name (index), the signal emitting object, and the passed arguments, for each signal of every QObject in my application without explicitly connecting to it?
Thanks!
No. The only generic API for monitoring signals is QSignalSpy, but that requires an explicit connection to a specific object and signal. The only other thing is the TestLib Framework, which has a command-line option (-vs) that can output all the emitted signals during a test run. But that seems pretty far removed from what you're asking for.
Of course, you can use QMetaObject to list all the signals of a QObject and try to explicitly monitor everything. But that presupposes you can get a reference to all the objects you might be interested in (and that you can actually know in advance what they will be).
The only exception to the above, is for signals that are emitted via a queued connection. These signals, which are most commonly emitted across threads, are wrapped in an event and posted to the event-queue of the receiver's thread. It is possible to detect these kinds of signals by filtering on events of type QEvent.MetaCall.
However, the associated event objects are of type QMetaCallEvent, which is an internal Qt class which is not wrapped by PyQt. Normally, these objects would have id(), sender(), signalId() and args() methods. But in PyQt, all you'll get is a plain QEvent, and thus no information about the emitted signal will be available.
Even if QMetaCallEvent was available, though, the default connection type is not queued - and there is no way to globally reset the default for all signals.
My guess is that the signal events you described are only used for queued connections. In this case events are sent to ensure slots are called after control is passed to the eventloop. Direct connections (wich you would use normally) are essentially just function calls and I doubt there is a way to intercept them without having access to the specific objects.
It is known that QWidget::paintEvent is triggered automatically the moment widget becomes visible or any event from the basic window happens. What should I do if I only want the paintEvent to be issued in response to update()?
It'd make no sense for a paintEvent not to be issued whenever the widget needs to be painted. Your reason to demand such an option means that you're trying to use the Qt API in a way it wasn't meant to be used. I can't quite imagine yet a particular design that would lead you to such use, sorry about that.
So, the only thing I can tell you is how you'd use update(). The idiomatic way of handling widget updates is as follows:
The source of data that the widget uses is updated. For example, the text or some variable affecting the visible contents is changed. Often this data is a Q_PROPERTY of the widget. The setter function is updating the member variable that stores the value and calls update(). The setter should not perform any expensive computations - they should be deferred until the paint event.
If the properties are changed multiple times before the event loop has a chance to run, the update events get coalesced. Internally, a call to update() results in posting an event to the event queue of the GUI thread. If there already is an update event in the queue for the given widget, the events get coalesced. The following invariant is preserved: at any given time, there can only be one update event for any particular widget in an event queue.
When the control returns to the event loop, the update event gets dispatched to the widget, ending up in calling your reimplementation of QWidget::paintEvent(...). This implementation should do the calculations necessary to paint the widget, and do the actual painting. If the calculations are extensive, they should be relegated to a worker thread.
Example
Let's say an application is receiving data from a serial port, modeled as a QIODevice (a QSerialPort is one). You could do as follows:
Connect QIODevice's readyRead signal to a slot in a parser QObject.
The slot receives and parses the data. It then emits a signal with processed data (for example, a vector of floating point values). This signal is connected to a newData slot in the widget.
The newData slot adds the data as-is to a queue, and schedules an update(). This is very fast if you're using Qt's data structures, or if your data class is modeled after them and uses implicit sharing with copy-on-write.
The update() dequeues all data sets and plots them. The QWidget::scroll() method comes handy for scrolling plots.
I know that we can't use GUI-interaction in non-GUI threads (QThread).
But I don't know if we can or can't interact with model (QAbstractItemModel) in threads and if True then how to do it in the right way?
I honestly searched something about this in Google and on SO and it seems like there are no relevant answers to my question.
What do you mean by "interact with model"? If you mean that you want to access the model from multiple threads by directly manipulating it, then you have to serialize the access to the model. Since there are so many methods within the model, I'd suggest you do not add a mutex within the model -- it'd be very tedious and error prone as it'd be too easy to forget a mutex locker. Instead, use the fact that your model inherits QObject, and thus can accept events.
Your gui thread accesses the model directly.
Other threads interact with the model by posting events to it (and perhaps receiving reply events).
The gui thread will process those events serially with any other access, thus protecting your model from concurrent access.
Other threads can of course receive replies from the model -- also via events. You'd have two event base classes: a Request class that is used to request things from the model, and then there'd be a Response event base class that the model would use to reply. The Request class should have a QObject* sender member, so that the model would know what QObject to post the reply event to. You'd probably want both the request and reply to carry identical identifier (say a serially increment int), so that requests and responses could be matched up.
You must implement all the threaded code that interacts with the model via events not by reimplementing QThread::run(), but within a QObject. After you instantiate the QObject, simply move it to a separate thread. QThread's default implementation of run() will spin an event loop to keep your QObject executing if there are any events, signals or timers ready for it. A zero-duration timer is a way of keeping a thread permanently busy, but make sure you don't do too much processing in one go, otherwise you'll delay processing of incoming events.
You can also use signals and slots, but you cannot call them directly, you can only:
connect() to them,
invoke them via QMetaObject::invokeMethod with Qt::QueuedConnection.
invoke them through a functor (say, a lambda) executed in the main thread context; see this answer for how to do that.
Behind the scenes, when you connect signals to slots of QObjects that reside in separate threads, Qt creates a connection that marshals each signal into a QMetaCallEvent, and then unmarshals it in the thread where the QObject with target slot lives.
It is hard for me to understand the difference between signals and events in Qt, could someone explain?
An event is a message encapsulated in a class (QEvent) which is processed in an event loop and dispatched to a recipient that can either accept the message or pass it along to others to process. They are usually created in response to external system events like mouse clicks.
Signals and Slots are a convenient way for QObjects to communicate with one another and are more similar to callback functions. In most circumstances, when a "signal" is emitted, any slot function connected to it is called directly. The exception is when signals and slots cross thread boundaries. In this case, the signal will essentially be converted into an event.
Events are something that happened to or within an object. In general, you would treat them within the object's own class code.
Signals are emitted by an object. The object is basically notifying other objects that something happened. Other objects might do something as a result or not, but this is not the emitter's job to deal with it.
My impression of the difference is as follows:
Say you have a server device, running an infinite loop, listening to some external client Events and reacting to them by executing some code.
(It can be a CPU, listening to interrupts from devices, or Client-side Javascript browser code, litsening for user clicks or Server-side website code, listening for users requesting web-pages or data).
Or it can be your Qt application, running its main loop.
I'll be explaining with the assumption that you're running Qt on Linux with an X-server used for drawing.
I can distinguish 2 main differences, although the second one is somewhat disputable:
Events represent your hardware and are a small finite set. Signals represent your Widgets-layer logic and can be arbitrarily complex and numerous.
Events are low-level messages, coming to you from the client. The set of Events is a strictly limited set (~20 different Event types), determined by hardware (e.g. mouse click/doubleclick/press/release, mouse move, keyboard key pressed/released/held etc.), and specified in the protocol of interaction (e.g. X protocol) between application and user.
E.g. at the time X protocol was created there were no multitouch gestures, there were only mouse and keyboard so X protocol won't understand your gestures and send them to application, it will just interpret them as mouse clicks. Thus, extensions to X protocol are introduced over time.
X events know nothing about widgets, widgets exist only in Qt. X events know only about X windows, which are very basic rectangles that your widgets consist of. Your Qt events are just a thin wrapper around X events/Windows events/Mac events, providing a compatibility layer between different Operating Systems native events for convenience of Widget-level logic layer authors.
Widget-level logic deals with Signals, cause they include the Widget-level meaning of your actions. Moreover, one Signal can be fired due to different events, e.g. either mouse click on "Save" menu button or a keyboard shortcut such as Ctrl-S.
Abstractly speaking (this is not exactly about Qt!), Events are asynchronous in their nature, while Signals (or hooks in other terms) are synchronous.
Say, you have a function foo(), that can fire Signal OR emit Event.
If it fires signal, Signal is executed in the same thread of code as the function, which caused it, right after the function.
On the other hand, if it emits Event, Event is sent to the main loop and it depends on the main loop, when it delivers that event to the receiving side and what happens next.
Thus 2 consecutive events may even get delivered in reversed order, while 2 consecutively fired signals remain consecutive.
Though, terminology is not strict. "Singals" in Unix as a means of Interprocess Communication should be better called Events, cause they are asynchronous: you call a signal in one process and never know, when the event loop is going to switch to the receiving process and execute the signal handler.
P.S. Please forgive me, if some of my examples are not absolutely correct in terms of letter. They are still good in terms of spirit.
An event is passed directly to an event handler method of a class. They are available for you to overload in your subclasses and choose how to handle the event differently. Events also pass up the chain from child to parent until someone handles it or it falls off the end.
Signals on the other hand are openly emitted and any other entity can opt to connect and listen to them. They pass through the event loops and are processed in a queue (they can also be handled directly if they are in the same thread).
There is an object of class QNetworkReply. There is a slot (in some other object) connected to its finished() signal. Signals are synchronous (the default ones). There is only one thread.
At some moment of time I want to get rid of both of the objects. No more signals or anything from them. I want them gone.
Well, I thought, I'll use
delete obj1; delete obj2;
But can I really?
The specs for ~QObject say:
Deleting a QObject while pending events are waiting to be delivered can cause a crash.
What are the 'pending events'?
Could that mean that while I'm calling my delete, there are already some 'pending events' to be delivered and that they may cause a crash and I cannot really check if there are any?
So let's say I call:
obj1->deleteLater(); obj2->deleteLater();
To be safe.
But, am I really safe? The deleteLater adds an event that will be handled in the main loop when control gets there. Can there be some pending events (signals) for obj1 or obj2 already there, waiting to be handled in the main loop before deleteLater will be handled? That would be very unfortunate. I don't want to write code checking for 'somewhat deleted' status and ignoring the incoming signal in all of my slots.
Deleting QObjects is usually safe (i.e. in normal practice; there might be pathological cases I am not aware of atm), if you follow two basic rules:
Never delete an object in a slot or method that is called directly or indirectly by a (synchronous, connection type "direct") signal from the object to be deleted.
E.g. if you have a class Operation with a signal Operation::finished() and a slot Manager::operationFinished(), you don't want delete the operation object that emitted the signal in that slot. The method emitting the finished() signal might continue accessing "this" after the emit (e.g. accessing a member), and then operate on an invalid "this" pointer.
Likewise, never delete an object in code that is called synchronously from the object's event handler. E.g. don't delete a SomeWidget in its SomeWidget::fooEvent() or in methods/slots you call from there. The event system will continue operating on the already deleted object -> Crash.
Both can be tricky to track down, as the backtraces usually look strange (Like crash while accessing a POD member variable), especially when you have complicated signal/slot chains where a deletion might occur several steps down originally initiated by a signal or event from the object that is deleted.
Such cases are the most common use case for deleteLater(). It makes sure that the current event can be completed before the control returns to the event loop, which then deletes the object. Another, I find often better way is defer the whole action by using a queued connection/QMetaObject::invokeMethod( ..., Qt::QueuedConnection ).
The next two lines of your referred docs says the answer.
From ~QObject,
Deleting a QObject while pending events are waiting to be delivered can cause a crash. You must not delete the QObject directly if it exists in a different thread than the one currently executing. Use deleteLater() instead, which will cause the event loop to delete the object after all pending events have been delivered to it.
It specifically says us to not to delete from other threads. Since you have a single threaded application, it is safe to delete QObject.
Else, if you have to delete it in a multi-threaded environment, use deleteLater() which will delete your QObject once the processing of all the events have been done.
You can find answer to your question reading about one of the Delta Object Rules which states this:
Signal Safe (SS).
It must be safe to
call methods on the object, including
the destructor, from within a slot
being called by one of its signals.
Fragment:
At its core, QObject supports being
deleted while signaling. In order to
take advantage of it you just have to
be sure your object does not try to
access any of its own members after
being deleted. However, most Qt
objects are not written this way, and
there is no requirement for them to be
either. For this reason, it is
recommended that you always call
deleteLater() if you need to delete an
object during one of its signals,
because odds are that ‘delete’ will
just crash the application.
Unfortunately, it is not always clear
when you should use ‘delete’ vs
deleteLater(). That is, it is not
always obvious that a code path has a
signal source. Often, you might have a
block of code that uses ‘delete’ on
some objects that is safe today, but
at some point in the future this same
block of code ends up getting invoked
from a signal source and now suddenly
your application is crashing. The only
general solution to this problem is to
use deleteLater() all the time, even
if at a glance it seems unnecessary.
Generally I regard Delta Object Rules as obligatory read for every Qt developer. It's excellent reading material.
As far as I know, this is mainly an issue if the objects exist in different threads. Or maybe while you are actually processing the signals.
Otherwise deleting a QObject will first disconnect all signals and slots and remove all pending events. As a call to disconnect() would do.