How does Qt determine which widgets gets the mouse events? - qt

Something I have been curious about is how Qt determines which widgets get the mouse events. I'm guessing that it keeps track of the current widget, which is how it decides which one gets click events. But how does it determine the current widget, and as an extension, mouse enter and leave events? Does it iterate through each top level widget and check if the cursor falls within the widget's bounding rect? And then ask all children of that widget, etc.?
I have been searching through the Qt source code but haven't been able to find where all of this starts. Any help is appreciated.

Related

How can child widget capture the mouse event under such circumstance

I need to simulate drag and drop in Qt, but I'm facing a problem. Here is the simplified version of the problem:
here you can see the action I took. I pressed the mouse in the area of parent widget and moved it to a child widget, keeping pressing, I did not release the mouse until it is moved into the child Widget. However, I found that the child widget could not capture the mouse release event when I released the mouse. (Actually, I found it was not only mouse release event, but also any other mouse event which was supposed to happen when the mouse was in the child widget)
Could someone give me a simple solution to do this? Maybe It is because the widget structure in my project is quite complicated so there is something wrong stops the transfer of the mouse event.
Try to accept mouse release event in parent widget, calculate mouse position, compare to child widget, and notify child widget Qt - Determine absolute widget and cursor position.
Or use QDrag and QMimeData if you want to pass data.

How to set a Slot receiving every Widget action in Qt

Suppose I've a Qt app based on QWidget, in which I'd like to obtain a "feedback" everytime I press a QPushButton, I rotate a QDial, I press a mouse button. My question is: how can I set a slot that informs me everytime something happened inside my app built for a touchscreen, in which I need to know when user does something on it.
MousePressEvent partially solves my problem; so when user touches the screen, MousePressEvent warns me about it. Problem is related to widgets as QPushButtons or QDials.
At the moment, I've already arranged my widgets with a lot of subwidgets; number of pushbutton is about 300. How can obtain triggering signal when one of them is pressed without re-edit every single button?
You can use an "event filter" that is installed on QApplication instance. This filter will receive all the events in your application, afterwards you can check event type and object type to pick the events you are interested in. See my answer to another question here for details.

Slider reacting on mouse wheel in entire application

By default QSlider reacts on mouse wheel only when cursor is on it. I want to control slider by mouse wheel not matter where the cursor is (of course only when my application has focus).
What's the best way to achieve that?
I just learned that mouse doesn't generate signals. So looks like I need to override wheelEvent in main window and use raise or lower method in it. But I guess that can cause double increment (or decrement) of slider value when mouse is hovering it.
So once again: What's the best way to achieve what I described?
You can override the wheelEvent() in your MainWindow and redirect it to your slider control, that is indeed one option.
Another option is to install an event filter on the qApp instance. This even filter then can check whether the event type is QEvent::Wheel, and when the receiver is not the slider, then again redirect it to the slider. Should work just as well.

Mouse button status

From what I see, QApplication::mouseButtons() may return no buttons even when a button is held down. This happens when you have clicked a side of a window for re-sizing. It's coherent with the docs because mouseButtons() reflects the state from the flow of QEvent::mouseButtonPress, etc. However, I need just to know if the button is held down. Does any one know if it's possible through the Qt API?
I think it's not possible. Mouse events outside an application's window are not passed to its event handlers. Dragging mouse borders is one of such events, it's processed by the window system. Another example is clicking on other windows. Usually an application doesn't know what the user does with other windows. You need to install system-wide event listener or use native API features(e.g. GetAsyncKeyState on Windows) to determine that. This behavior is unusual and possibly dangerous. In most cases it's not useful, and it seems that Qt doesn't have this ability.

How to detect a mouse click inside a tooltip in Qt?

I have a Qt application in which certain QLabel's display a tooltip if a certain internal condition occurs.
Since the tooltip has a timeout and is hidden by Qt automatically, the tooltip is kept alive by the application by showing the tooltip every 3 seconds (I did not find any mechanism to tell Qt to show a tooltip indefinitely).
The tooltip is displayed until the user clicks on the QLabel itself: the tooltip is not refreshed any more and disappears.
I now have a new requirement that the tooltip should also disappear if the user clicks on the tooltip itself. Is there a signal that is sent when the user clicks on a visible tooltip? Or is it necessary to use some more sophisticated technique?
EDIT
I have checked my code again, here is some extra information.
Qt does detect a mouse click on a tooltip and hides it, but the application immediately shows the tooltip again.
What I would like to do is that Qt informs my code of the mouse-clicked event, so that it stops showing the tooltip again and again. I have two possible solutions in mind, but I do not know if either of them is technically feasible:
Remove tooltip timeout: when a tooltip is shown, it remains visible as long as the user does not click on it. How can I display a tooltip without a timeout in Qt?
Keep the tooltip visible by repeatedly showing it; detect a mouse clicked on the tooltip in order to stop the keep-alive loop. How do I receive a signal when the user clicks on a tooltip?
Under the hood, the actual class that implements the tooltip is a private QLabel-derived class called QTipLabel:
http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/kernel/qtooltip.cpp#line119
There's nothing published in the interface to get at an instance of that class from QToolTip, so intercepting clicks would only be done with some sort of ill-advised hack.
That said: among the events that should "hideTipImmediately" is QEvent::mouseButtonPress...in fact, there's an event filter installed so that any click in the app will hide it:
http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/kernel/qtooltip.cpp#line325
So if you're not seeing the tooltip disappear when it's being clicked on, there's a bug. (Clicking on tooltips hides them for me in Qt-based apps under Kubuntu.)
Note the definition of QToolTip::showText:
void QToolTip::showText ( const QPoint & pos, const QString & text,
QWidget * w, const QRect & rect ) [static] Shows text as a tool tip,
with the global position pos as the point of interest. The tool tip
will be shown with a platform specific offset from this point of
interest.
If you specify a non-empty rect the tip will be hidden as soon as you
move your cursor out of this area.
The rect is in the coordinates of the widget you specify with w. If
the rect is not empty you must specify a widget. Otherwise this
argument can be 0 but it is used to determine the appropriate screen
on multi-head systems.
If text is empty the tool tip is hidden. If the text is the same as
the currently shown tooltip, the tip will not move. You can force
moving by first hiding the tip with an empty text, and then showing
the new tip at the new position.
Thus, you can supply the rectangle in which the QToolTip is to be presented. Then, if what you want to do is close the QToolTip only when the user clicks on it, you can capture mouseButtonPress events as #HostileFork pointed out and then close the tooltip only when the coordinates of the event fall within it.

Resources