Post events without specifying target object in Qt - qt

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

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:
There are native messages/events, delivered by the operating system, usually received by a window-specific event loop.
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:
Identify what top-level window (widget) the event should go to. You can enumerate top level widgets via qApp->topLevelWidgets().
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.
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).

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.

Related

Is there a way to add a mouse event to a thread?

I have a suspicion that something is preventing my mouse event to be called in Qt. Therefore, I think it might help to add the event to a thread. Is there any way to do that? And if so how would the syntax look?
Qt standard mouse events come to QWidget objects. Those must exist in the main thread, always.
So no, you can't receive the normal mouse events in other threads.
However, you should perhaps install an event filter to your main window or to your qApp object, so you will see all the events. Look in the docs for how to use the event filter, but in short, you need to subclass QObject to override the eventFilter method, and then create instance of this class, and install that as event filter for another object.

How to catch all and only button release events in Qt?

My team is developing an UI for an apparatus with touch screen and we would like it to emit a sound (from a buzzer) each time the user correctly presses a button (so using the release event). Notice that I don't want to play the sound after each click on the interface, but only when the click is over a button.
We use many types of button, sometimes QPushButton and most of the times customized buttons derived from QAbstractButton. In most cases these buttons get an objectName.
So I supposed in order to do that, I would have to catch the MouseButtonRelease event and since I'm already working with a subclass of QApplication to handle excetions, I decided to do this in the notify function.
I tried, then, some methods to recognized when the MouseButtonRelease was related to a button but none of them were successfull. The best one, verifying the receiver's objectName was still not good enought not only because not all buttons had an objectName (which, of course, can be handled), but specially because not always the event was caught for buttons with names set. In other words, sometimes I would click in a button and it recognizes the event and sometimes I would click in the same button and the event is not recognized.
I did some research and another method I found was to set an event filter in the MainWindow, but not all widgets have the MainWindow as their parent which means I would have to Ctrl+c / Ctrl+V the same code time after time when I obviously want something more localized (i.e. in only one spot).
So why it happens that the notify not always handles the events? And how could I do this? Any suggestions are appreciated specially one that is less heavier then handling the events globally.
As info, the other two ways I tried to catch the events with similar or even worst results inside notify were with receiver->inherits("...") and qobject_cast< QAbstractButton* >(receiver).

qt model/view: how qt knows when to run default signal handlers, if I've reimplemented event handlers?

I've got a general question on qt design.
Say, I created a custom classes, impelementing QAbstractTableModel and QTableView class. I've re-implemented event handlers in View, such as mousePressed, mouseRelease etc.
Still Qt's View manages to perform some of its default functionality: it still responds to mouse clicks and movements on cells by changing selection, thus it somehow fires selectionModel "built-in" signals, though I didn't ask it to. It still resizes columns, if I drag on cell borders etc. What's the mechanism that triggers those "buit-in, default slots" and how can I disable some parts of it? E.g. if I want to disable default behavior of selectionModel or default resize?
For the sake of comparison, in gtk+ there's a concept of default per-class signal handler, which is a function, by default connected to its signal and called prior or after your custom per-class or per-object signal handlers, depending on parameters you set. You can disable it from your custom slot, if you want to and thoroughly control behavior of e.g. resize or selection.
Is Qt opaque in this place and provides customization via its interface functions only? My question is particularly related to pyqt. Please ask for clarification, if I'm too vague.
The event handlers that you refer to are used to listen to events, not to filter them. You can't override any events in them, since they don't have a return value: there's no way to inform subsequent event processing that you don't wish it to run.
To filter events, you must reimplement the event method, and invoke the base class's implementation on events that you do not wish to filter.
In Qt, event handling is done per-object, and you can install external objects as event filters on any other object. An object receives the events in its event method. The QObject class implements this method and invokes the timerEvent method. The QWidget class reimplements this method and invokes the widget-specific xxxEvent methods. And so on. All of those classes still process some events internally. Those are the per-class handlers that you speak of.

Qt: How to initialize dialog widgets?

I would like to know what the established procedure is for initializing the controls within a Qt custom dialog box. In the code I am writing, the dialog would present a QListView containing directories from an object passed (by reference) to the dialog class during construction. When the dialog is displayed, I obviously want the list to display the directories currently configured in the object.
Where should this be done though? Perhaps in the overridden showEvent() method?
Background: I used to do a lot of MFC programming back in the day, and would have done this sort of stuff in the OnCreate method, or some such, once the window object had been created.
Thankfully Qt doesn't require you to do any hooking to find the moment to create things (unless you want to). If you look over the Qt examples for dialogs, most do all the constructing in the constructor:
http://doc.qt.io/archives/qt-4.7/examples-dialogs.html
The tab dialog example--for instance--doesn't do "on-demand" initializing of tabs. Although you could wire something up via the currentChanged signal:
http://doc.qt.io/archives/qt-4.7/qtabwidget.html#currentChanged
Wizard-style dialogs have initializePage and cleanupPage methods:
http://doc.qt.io/archives/qt-4.7/qwizardpage.html#initializePage
http://doc.qt.io/archives/qt-4.7/qwizardpage.html#cleanupPage
But by and large, you can just use the constructor. I guess the main exception would be if find yourself allocating the dialog at a much earlier time from when you actually display it (via exec), and you don't want to bear the performance burden for some part of that until it's actually shown. Such cases should be rare and probably the easiest thing to do is just add your own function that you call (like finalizeCreationBeforeExec).

QWidget signal sent when menu action selected - how do I prevent this?

In more than one of my Qt applications I've noticed that, whenever the menu bar is clicked, the last signal to have been sent from a widget within the GUI is re-sent before the menu action is invoked. Most of the time this doesn't matter; but on some occasions it matters very much.
In a few cases where the widget's signal is connected to one of its own slots, it's straightforward to begin the slot with a
if (hasFocus())
{
// ...
}
...block so that such spurious signals, not generated by the user actually clicking on the widget, can be ignored.
However, I've recently identified that this behaviour is responsible for several related bugs where the spurious signals are passed on through several layers of the program before being acted upon, so simply checking whether a particular widget has focus is not trivial to implement.
My question, therefore, is:
why on earth does clicking on a menu item cause a signal to be emitted from a widget elsewhere on the screen? I can't find this behaviour documented anywhere?
how do I stop it?
Many thanks,
Stephen.
As you deduced yourself, the QLineEdit::editingFinished signal can be emitted twice if the user press enter and the QLineEdit loses the focus later. An old bug was created but behaviour has not been changed : https://bugreports.qt.io/browse/QTBUG-40.
Your solution is fine : overload QLineEdit and check if the value has changed before triggering the signal. You can use the flag QLineEdit::isModified for the check : it has a default value of false and is changed to true whenever the user changes the line edit's contents. It has to be manually reset to false when you emit the signal.
You can also do that check in the receiver object, just checking if the value has a meaning (is different from the last recorded value for example) and process it or not.
Therefore the polluting signals would not be a problem. It is in my opinion the cleanest solution, then you have a robust model. Because the user could also hit enter a few times with the same text value and you have to handle this anyway.
You can also use QLineEdit::returnPressed but this requires the user to always press enter to validate a value. Not always intuitive but forces the user to explicitly validate the inputs.

Resources