我正在尝试创建一个可拆卸的样式小部件,就像Chrome标签可拆卸一样(类称为Tab).我有一切工作,除了有时(可能有50%的时间)的错误,Tab对象永远不会获得鼠标释放事件,并停止获取鼠标移动事件.
从本质上讲,分离系统的工作原理是允许拖动鼠标按下/移动/释放功能,就像正常情况一样. mouseMoveEvent检查从开始移动的总距离,如果超过一定量,将启动“分离”过程.分离过程涉及将父窗口小部件设置为0(顶级窗口小部件,未修饰的窗口),因此Tab对象几乎浮动在鼠标下方的所有内容上,并继续与其一起拖动直到释放.
我浏览了所有正在交付的QEvent项目,我发现当出现此问题时,QEvent :: MouseMove项目(以及此后的所有鼠标事件)将被发送到TabBar(Tab对象的原始父项).这在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创建最顶层的窗口小部件(让我们称之为Shade)(并且可以使用Qt :: WA_TranslucentBackground).您可以通过重新实现paintEvent来使用Shade外观进行操作.例如 – 绘制原始窗口小部件的内容,或绘制一些透明预览等.
然后,您可以在拖动期间调整Shade的大小,以向用户显示该窗口小部件将被分离.你不会松动鼠标捕获.
当用户释放鼠标时 – 你会记住Shade的位置,将其破坏并分离移动原始小部件.
如果您想了解更多细节,请随时询问.