Reputation: 825
On Windows 7 to be specific, while I don't think it matters.
We have all seen this issue in countless desktop applications, especially games that tend not to use OS-supplied controls: when the screen changes programmatically under a motionless mouse cursor (as opposed to user moving the cursor to a new widget), they go out of sync. Either the cursor does not change or the widget is not painted as it should be with the cursor inside it - obviously the widget's mouse enter
event is not triggered. If you shake the mouse a bit without even leaving the widget, the thing fixes itself.
Sadly, Qt 5.7 shares this widespread problem. The first solution to come to mind is to move the mouse programmatically to (0, 0)
and back by Windows means. However, it's not cross-platform(ish). Any better ideas?
Upvotes: 4
Views: 2050
Reputation: 8049
I found two solutions.
The first one is a simple hack: Call widget->hide()
and then immediately widget->show()
. This will reevaluate and update the widget's visual state depending on whether it is under mouse cursor or not, even if the cursor has not moved. But I would not recommend this solution because it might have some unwanted side effects. Though I have not encountered any yet.
The second solution is better because it does not look like a hack and it probably does not have any side effects:
widget->setAttribute(Qt::WA_UnderCursor, qApp->widgetAt(QCursor::pos()) == widget);
widget->update();
The code is assumed to be called from widget's parent. But you can adjust it and calle it from any other place. Note: it is better to use QApplication::widgetAt()
than widget->rect().contains()
, which is suggested in another answers, because in the latter case we would get false positives for widgets which are overlayed by other widgets.
What is actually complicated, is to find the place in code from where you should call this. Because there can be many sources of the widget's motion - moving withing its parent, moving of parent(s), resizing, resizing of parent(s), scrolling etc. This is probably the reason why this would be too complicated to implement this to standard Qt widget library. It would be probably a performance killer in some scenarios. (my guess)
Just to show my usage: I am moving a whole container widget which contains many child widgets. Subsequently one of the child widgets may get under the cursor after the container is moved. So I call:
containerWidget->move(dx, dy); // this moves the container
for (QWidget *child : containerWidget->findChildren<QWidget*>())
{
child->setAttribute(Qt::WA_UnderMouse, qApp->widgetAt(QCursor::pos()) == child);
child->update();
}
Upvotes: 0
Reputation: 169
I don't know if your question is still actual
You can override method underMouse()
with following code:
bool MyWidget::underMouse()
{
return rect().contains(mapFromGlobal(QCursor::pos()));
}
Events moveEvent
or resizeEvent
in the rest panels will be definitely triggered when splitter resizes panel. All you need is check if widget is under mouse and then invoke enterEvent()
manually
Upvotes: 1