Post events without specifying target object in Qt
Asked Answered
P

2

7

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

Plethora answered 12/2, 2012 at 7:2 Comment(4)
#8730008 should answer your question I think.Blodgett
Thank you Mat, it's a good start, but what I need to know if it's possible to register objects to "listen" for a specific event. I mean, if I send a "hello" event, have or register objects that respond to that eventPlethora
It doesn't make sense in Qt to have an event without a receiver. Perhaps you could say what you're actually trying to accomplish here? From what you're describing it seems like you should be using signals/slots rather than sending QEvents.Signature
Thanks Dan, I was so confused, you are right, to do what I want, I should use signal/slots, but my confusion is now, how is that the QMouseEvent works, I mean, how is that the QMouseEvent class can receive events from the mouse when I have a QMainWindow.Plethora
M
2

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).

Mcneal answered 5/6, 2012 at 17:9 Comment(8)
I have the same issue at the moment. I want to post an event into my application from the top level (i.e. as though it came from outside) so I don't want to specify a specific object, except perhaps the application itself?Steatite
@Steatite This is nonsense unless you're talking about synthesizing the GUI events. If that's what you want, then you should look at the test framework that's part of Qt.Galatia
@Steatite Or, if you claim it to make sense, then please elucidate the exact scenario you're after, and an exact example of an "event" you want to send.Galatia
It IS nonsense, in general. But we have an issue where our mouse click comes in at the wrong position and I want to resend it with corrected posistion. If its possible then please let me know, if not then please put me out of my misery! :o, thanks!Steatite
@Steatite How would you know that it comes in at the wrong position? Suppose I give you screen coordinates of the click, what do you do with it next to determine it's wrong?Galatia
#8730008 has some code for injecting mouse events.Mcelhaney
Let's say I want to synthetize a "mouse left button press" event that would embed basic information (baiscally the same information as if it was coming from the windowing syustem - Windows7 in my case, but it would be synthetized from my application and not be a real mouse click). Ideally, I would like to post this event to the application event loop, and let QT's internal algorithm decides the widget that should receive the event first... Is it something that is possible ?Preexist
Right now, the only way to do this for me was to use Windows API, but I was wondering if I coumld do it with QT (something like posting a system-like message to the nativeEventFilter ?)Preexist
G
1

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.

Gushy answered 27/2, 2017 at 10:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.