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