【问题标题】:Change QWidget Parent During Mouse Event在鼠标事件期间更改 QWidget 父级
【发布时间】:2014-10-29 03:39:58
【问题描述】:

我正在尝试创建一个可拆卸的类型样式小部件,就像 Chrome 选项卡可拆卸的方式一样(类称为 Tab)。我一切正常,除了一个错误,有时(可能 50% 的时间)Tab 对象永远不会获得鼠标释放事件,并且停止获得鼠标移动事件。

基本上,分离系统的工作原理是允许在鼠标按下/移动/释放功能中进行拖动,就像正常情况一样。 mouseMoveEvent 检查从开始移动的总距离,如果超过一定量,将开始“分离”过程。分离过程涉及将父小部件设置为 0(顶级小部件,未装饰的窗口),因此 Tab 对象几乎漂浮在鼠标下方的所有内容之上,并继续与它一起拖动直到释放。

我浏览了所有正在交付的QEvent 项目,我发现当这个问题发生时,QEvent::MouseMove 项目(以及之后的所有鼠标事件)被发送到 TabBar(Tab 对象的原始父项) )。这在选项卡上调用setParent(0) 后直接发生。

基本鼠标处理概述:

void Tab::mousePressEvent(*) {
    [set up some boolean, start positions, etc]
}
void Tab::mouseMoveEvent(*) {
    [track the updated position]
    if (positionChange > STATIC_AMOUNT)
        detachTab();
}
void Tab::mouseReleaseEvent(*) {
    [return the Tab to its original position, and set the parent back to the TabBar]
}
void Tab::detachTab() {
    QPoint mappedPos = mapToGlobal(0, 0);
    setParent(0);    //The loss of MouseMove events occurs when this returns.
    move(mappedPos);
    show();
    raise();
}

这里是Tab对象接收到的事件(第一行是QEvent类型,第二行是名字)

[Tab::detachTab() started]
[setParent(0) started]
QEvent::Hide
QEvent::Leave
qApp QEvent::MouseMove [ TabBar ]    <--  now the TabBar is soaking up the mouse events
QEvent::HideToParent
QEvent::ParentAboutToChange
QEvent::ParentChange
[setParent(0) returned]
....

总结:我的可拖动 QWidget 在其父级设置为 0 后丢失了 QEvent::MouseMove 和 QEvent::MouseButtonRelease 事件。

任何建议将不胜感激!

【问题讨论】:

  • 可能需要直接使用grabMouse方法。但是我不确定当你删除一个小部件时抓取是否会被释放。

标签: c++ qt qt5 qwidget


【解决方案1】:

有点棘手的解决方法。我没有测试它,这只是一个想法。

当您的鼠标悬停在小部件的可拖动部分时,您可以使用Qt::FramelessWindowHint(也可以使用Qt::WA_TranslucentBackground)创建最顶部的小部件(我们称之为Shade)。您可以通过重新实现 paintEvent 来操作 Shade 外观。例如 - 绘制原始小部件的内容,或者绘制一些透明预览等。

然后您可以在拖动过程中调整 Shade 的大小,以向用户显示小部件将被分离。您不会丢失鼠标捕获。

当用户释放鼠标时 - 你会记住 Shade 的位置,销毁它并分离+移动原始小部件。


如果您想了解更多详情,请随时询问。

【讨论】:

  • 感谢 Dmitry 的解决方法。理想情况下,我不想做这样的事情,但这很可能会奏效。
  • 据我所知,WinAPI 中正在做这样的事情。我们正计划实现我们自己的码头管理器,所以我们采用这种方式。
  • 我尝试了您使用grabMousereleaseMouse 的建议,效果很好。如果我回到这个问题并找到鼠标事件丢失的核心问题,我一定会报告!
  • 好的,但要小心这种方法。当您单击小部件时,此方法会自动调用。因此,如果您忘记释放捕获,您可能需要重置操作系统。
【解决方案2】:

这里是similar question
所以你假设使用QDocWidget 并使用tabifyDockWidget 强制堆叠这些小部件。

【讨论】:

  • 我只是对我的所有结构使用普通的子类 QWidgets,而不是 QDocWidgets。
  • 我可以看到。我只是指出您正在尝试做一些已经提供的事情。无论如何,您始终可以将小部件放入QDocWidget
猜你喜欢
  • 2012-03-01
  • 2014-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-06
  • 2020-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多