How can child widget capture the mouse event under such circumstance - qt

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.

Related

How does Qt determine which widgets gets the mouse events?

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.

Qt: display qgraphicsitem in a widget

I got a QGraphicsScene that contains QGraphicsItems. On clicking such an item I open a dialog. I now want the item to be displayed in an area of the dialog.
I tried a QGraphicsView (in the dialog) and "pointed" it to the item which works allmost perfectly. The problem is, that it is possible to click the item in the dialog which would open a new dialog.
So my question: is there a easy way to tell QGraphicsView to ignore any input events? If not, is there a easy way to display a QGraphicsItem within a widget?
I am feeling so stupid...
QGraphicsView::setInteractive(false) did the trick.
I am still able to move the icon with the mouse wheel but this can probably be avoided by restricting the scene rect with setSceneRect()
You can install an event filter, on the QGraphicsView, which ignores input events. The Qt documentation states:
In your reimplementation of this function, if you want to filter the event out, i.e. stop it being handled further, return true; otherwise return false.

How to check if the mouse has really left the QWidget?

Consider a QWidget window, what event is triggered when the mouse has left this window?
The window has QLineEdit fields on it and they have completers (QCompleter) for input suggestions. The actual goal is to make such an (open) completer disappear when the mouse leaves the window. This is mostly because in some environments, moving the mouse over a different window may focus that other window, but keyboard events are still sent to the QLineEdit field (even though its parent window isn't focused anymore), which is confusing.
I could implement QWidget::leaveEvent(QEvent *event) (in the window), find the currently shown completer popup and hide it, that closes the popup. But ironically, leaveEvent() is also triggered when the mouse is moved over that popup - hiding it (making it impossible to click on an item in that popup). I guess that makes sense because the popup is a different QWidget, even though the popup is indirectly owned by the window.
So how do I check if the mouse has actually left the QWidget window?
Reimplement QWidget::leaveEvent(QEvent *event) in your derived class but start by checking that rect().contains(mapFromGlobal(QCursor::pos())) is true.
If not, return without doing anything.
This should filter out all the events where the mouse is still over your widget.
Hope it helps!

Qt: Can mouse event handlers block one another?

I have a simple parent widget that reimplements mousePressEvent/mouseReleaseEvent. The parent's child widgets use enterEvent/leaveEvent. When I hover the mouse over the child widgets, leaveEvent/enterEvent executes, but when I click and hold the mouse, mousePressEvent executes, but enterEvent/leaveEvent goes silent (in other words, no click and drag). Any ideas about what could be causing this?
If you press and hold down the mouse button on a widget then that widget grabs mouse events until you release the button. This is not a special feature of Qt, you can find similar behaviour in every other GUI APIs I know.
Take a look at the relevant part of the Qt documentation:
QWidget / Events:
mousePressEvent() is called when a mouse button is pressed while the
mouse cursor is inside the widget, or when the widget has grabbed the
mouse using grabMouse(). Pressing the mouse without releasing it is
effectively the same as calling grabMouse().
void QWidget::grabMouse ():
Grabs the mouse input. This widget receives all mouse events until
releaseMouse() is called; other widgets get no mouse events at all.

How to force calling of QWidget::paintEvent() when its hovered by other window?

I have a problem:
I'm creating a widget which displays current date's day number. It's like a button, but it's not derived from QPushButton class. Just from QWidget. So I've reimplemented enterEvent(), leaveEvent(), mousePressEvent(), mouseReleaseEvent(). I do call update() inside these methods and widget has realistic button behavior (paintEvent() is reimplemented also).
But when I change system date and hover that widget with other window, my widget doesn't get paintEvent() and the old date is displayed. Only when I place mouse over it, widget repaints it's contents.
I guess there is a feature (like buffering) which paints old contents on hovering with other window to avoid unnecessary recalculations. But I need to disable it. Tried to set many attributes (the Qt::WidgetAttribute enum). But it doesn't work.
I think you should find a way to detect that the system time has changed and call update() when that happens. Any other method (like detecting the "hovering" of a window or waiting for a mouse event) will cause the update to occur too late.

Resources