Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Post events without specifying target object in Qt

Tags:

events

qt

qevent

I need help to understand to use QEvents in QT, this is driving me crazy.

I am writting an application using custom events, but as in QApplication::postEvent function, it's necesary to specify the target object.

As I understand, it's possible to post events to Qt's event loop with

QApplication::postEvent(obj_target, QEvent myevent);

This means that I'm trying to catch "myevent" event in obj_target an do some stuff.

But I need to post events without specify a target object, as QMouseEvent or QKeyEvent do

  • I mean, when clicking in a QMainWindow with a lot of buttons, how is that I can click any button and that button is pressed?

  • What is the target object when the click event is posted?

  • It's possible to register objects to "listen" for a specific event?

I'm really confused, it's possible to post an event without specifying a target object?

Thank you very much in advance

like image 525
Hermandroid Avatar asked Feb 12 '12 07:02

Hermandroid


People also ask

What is eventFilter in Qt?

Event Filters The QObject::installEventFilter() function enables this by setting up an event filter, causing a nominated filter object to receive the events for a target object in its QObject::eventFilter() function.

What is event loop in Qt?

An event loop in a thread makes it possible for the thread to use certain non-GUI Qt classes that require the presence of an event loop (such as QTimer, QTcpSocket, and QProcess). It also makes it possible to connect signals from any threads to slots of a specific thread.

How do Qt events work?

When an event occurs, Qt creates an event object to represent it by constructing an instance of the appropriate QEvent subclass, and delivers it to a particular instance of QObject (or one of its subclasses) by calling its event() function.


2 Answers

There is no trivial way to post events "globally", as Dan has said. All of the event dispatching of native events is done by private Qt implementation code.

The important distinction is:

  1. There are native messages/events, delivered by the operating system, usually received by a window-specific event loop.

  2. There are QEvents.

Internally, Qt keeps track of the top-level Widgets (windows, really), so when it receives an event from the OS, it knows which window it should go to - it can match it using the platform window id, for example.

QEvent delivery makes no sense without a receiving object, since sending an event to an object really only means that QObject::event(QEvent*) method is called on that object. It's impossible to call this method without having an object instance!

If you want to synthesize a global key press or mouse click event, then you have to figure out what object the event goes to. Namely:

  1. Identify what top-level window (widget) the event should go to. You can enumerate top level widgets via qApp->topLevelWidgets().

  2. Identify the child widget the event should go to. If it's a keyboard event, then sending the event to currently focused widget via qApp->focusWidget() is sufficient. You need to enumerate the child widgets to find the deepest one in the tree that overlaps the mouse coordinates.

  3. Send the correct QEvent subclass to the widget you've just identified. Events delivered to top-level widgets will be routed to the correct child widget.

When sending mouse events, you also need to synthesize relevant enter and leave events, or you risk leaving the widgets in an invalid state. The application.cpp source file should give you some ideas there.

This doesn't give you access to native graphical items, such as menus on OS X.

Please tell us exactly what you're trying to do. Why do you want to post a broadcast event? Who receives it? Since your own QObject-derived classes will receive those broadcasts, I presume, it's easy enough to use signal-slot mechanism. You'd simply connect(...) those receiver classes to some global broadcaster QObject's signal(s).

like image 178
Kuba hasn't forgotten Monica Avatar answered Oct 26 '22 23:10

Kuba hasn't forgotten Monica


For this purpose, I have a specific singleton class which I call GuiSignalHub. It regroups all the application-wide signals.

Objects that want to trigger an application-level action (such as opening context help) just connect their signal to the GuiSignalHub signal. Receivers just connect the GuiSignalHub to their slot.

like image 44
galinette Avatar answered Oct 26 '22 23:10

galinette