【问题标题】:How to force Qt update the widget under mouse?如何强制 Qt 更新鼠标下的小部件?
【发布时间】:2021-04-05 02:52:56
【问题描述】:

具体来说是在 Windows 7 上,虽然我认为这并不重要。

我们在无数桌面应用程序中都看到过这个问题,尤其是那些倾向于不使用操作系统提供的控件的游戏:当屏幕在静止的鼠标光标下以编程方式改变时(而不是用户将光标移动到新的小部件),他们不同步。光标没有改变,或者小部件没有像它应该在里面那样被绘制——显然小部件的mouse enter 事件没有被触发。如果您在不离开小部件的情况下稍微摇动鼠标,事情就会自行修复。

遗憾的是,Qt 5.7 也存在这个普遍存在的问题。想到的第一个解决方案是以编程方式将鼠标移动到 (0, 0) 并通过 Windows 方式返回。但是,它不是跨平台的(ish)。有更好的想法吗?

【问题讨论】:

  • “屏幕以编程方式更改”到底是什么意思?您在 Qt 中遇到的问题在哪里?
  • @Kamajii 我有一个继承自QSplitter 的拆分器,其中有一系列继承自QPanel 的面板。每个面板都有一个关闭按钮。当用户单击此按钮时,面板将关闭,并且拆分器会调整其他面板的大小,以便新面板占用其空间。但是,对于现在位于鼠标光标下的这个新面板 enterEvent() 没有被调用并且面板被绘制错误。摇动鼠标会有帮助。
  • 在鼠标下的widget上调用QWidget::update能解决你的问题吗?
  • @m7913d 是我尝试的第一件事。它没有。
  • 你能在尽可能小的代码示例中重现并添加它吗?

标签: c++ qt


【解决方案1】:

我不知道你的问题是否仍然存在

您可以使用以下代码覆盖方法underMouse():

bool MyWidget::underMouse()
{
    return rect().contains(mapFromGlobal(QCursor::pos()));
}

拆分器调整面板大小时,肯定会触发其余面板中的事件moveEvent 或resizeEvent。您只需要检查小部件是否在鼠标下,然后手动调用enterEvent()

【讨论】:

  • 准确地说,你不能重写这个方法,因为它不是虚拟的。
  • 使用QApplication::widgetAt() 比使用widget->rect().contains() 更好,因为在后一种情况下,我们会得到被其他小部件覆盖的小部件的误报
【解决方案2】:

我找到了两个解决方案。

第一个是简单的 hack:致电 widget->hide(),然后立即致电 widget->show()。这将根据它是否在鼠标光标下重新评估和更新小部件的视觉状态,即使光标没有移动。但我不会推荐这种解决方案,因为它可能会产生一些不需要的副作用。虽然我还没有遇到过。

第二种解决方案更好,因为它看起来不像黑客,而且可能没有任何副作用:

widget->setAttribute(Qt::WA_UnderCursor, qApp->widgetAt(QCursor::pos()) == widget);
widget->update();

假定代码是从小部件的父级调用的。但是您可以调整它并从任何其他地方调用它。注意:使用QApplication::widgetAt() 比使用widget->rect().contains() 更好,这是在另一个答案中建议的,因为在后一种情况下,我们会得到被其他小部件覆盖的小部件的误报。

真正复杂的是在代码中找到应该调用它的位置。因为小部件的运动可能有很多来源 - 与父级一起移动、父级移动、调整大小、调整父级大小、滚动等。这可能是实现这一点过于复杂的原因标准 Qt 小部件库。在某些情况下,它可能会成为性能杀手。 (我的猜测)

只是为了展示我的用法:我正在移动一个包含许多子小部件的整个容器小部件。随后,在容器移动后,其中一个子小部件可能会位于光标下。所以我打电话:

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();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-12
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    相关资源
    最近更新 更多