ekhan
ekhan

Reputation: 251

Event Queue in Qt

How many event queues are there in Qt application? Events like click etc are enqueued in the queue. And you can also enque events using function like postEvent. Are all these events in the same queue? if yes is there a way to define different queues?

Upvotes: 1

Views: 4390

Answers (1)

Normally, there is at most one event queue per each thread.

It is possible to have additional event queues, with two implementation strategies that differ on whether you remain compatible with QCoreApplication::postEvent.

If you don't care about QCoreApplication::postEvent working with your queue, everything is up to you. You can implement the queue in whatever way you wish. Note that Qt doesn't implement a way of marking a QObject as belonging to a particular event queue. When you're ready to deliver the events from your queue, you simply invoke QCoreApplication::notify, passing it the target object pointer, and event pointer. Easy-peasy. You don't have any control over the events that are delivered to any and all objects from the default queue, of course.

Another way is to remain compatible with QCoreApplication::postEvent. Namely, you somehow "mark" an object as having its events handled by your queue. You intercept the event about to be delivered to the target, enqueue it, and handle it yourself as needed.

This is the QStateMachine-like hack. It is good. And bad. And things in between. It's worth knowing how it's done and why.

Hierarchical state machines typically need to control the delivery of events and inject their own events into the queue, in front of other events. This is so that the state transition events are delivered in right order in relation to the events that cause the transitions; furthermore sometimes a transition-causing event might need to be delivered multiple times, retained for later delivery, etc.

This is all in the face of the rigid event lifetime enforced by the default event dispatching system. To work around it, QStateMachine implements its own event queue. Whenever you declare a transition on an event that would be delivered to some object, the state machine installs itself as an event filter on that object.

Then, whenever the original event reaches the target object, the filter intercepts the event and prevents its delivery to the target object. Now it must make a copy of the event, and insert it into its own queue. The copy must be made, because the event will be deleted by the event dispatcher as soon as the control leaves the event filter and/or the target object's event() method.

Unfortunately, before Qt 6, QEvents were not cloneable - at least not publicly so. There was some clone functionality hidden in Qt's innards, usable by user code, but it was a private API, and not based on the virtual copy constructor idiom.

Qt 6 has added the QEvent::clone method, and events should be presumed cloneable. Custom events in legacy code that wasn’t ported to Qt 6 won’t support this, and their clones will not be fully functional if they carry data.

Using the filter-based idiom/hack, you can implement a notion of a QObject belonging to a certain event queue. When your queue filters the events on the target object, clones them, and enqueues them for separate delivery, the object functionally resides on your event queue. When no such filtering takes place, the object resides on the default per-thread queue. You can also only intercept events of the type(s) your queue is interested in, just like the QStateMachine does.

Upvotes: 3

Related Questions