在鼠标事件期间更改QWidget父项

Change QWidget Parent During Mouse Event

本文关键字:QWidget 父项 鼠标 事件      更新时间:2023-10-16

我正在尝试创建一个可拆卸类型的小部件,就像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事件。

任何建议都将不胜感激!

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

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

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

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


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

这里有一个类似的问题
因此,您假设使用QDocWidget,并使用tabifyDockWidget强制堆叠这些小部件。