Qt 界面无边框 拖拽移动 问题处理:setMouseTracking(true)无法跟踪鼠标事件
问题1: setMouseTracking(true)无法跟踪鼠标事件
问题原因:
底层界面widgetA, 在此之上 要搭建很多顶层界面, 比如: 最顶层导航栏WidgetB, 左边导航栏widgetC, 中间界面WIdgetD,并且这些界面完全覆盖了底层界面, 就会导致鼠标移动事件被拦截。
【当然距离底层界面四周有一定的间距 不影响, 有些gitee github 上提供的代码 是用 setMouseTracking(true) 实现无边框拖拽, 最终发现四周的边框间距 都有一定的间距 至少1px】
解决方法:
setAttribute(Qt::WA_Hover); //代替 setMouseTracking(true)
bool DSMainWindow::event(QEvent *event)
{
if (event->type() == QEvent::HoverMove)
{
QHoverEvent *hoverEvent = static_cast<QHoverEvent *>(event);
...
...
}
return QWidget::event(event);
}
具体问题原因分析:(猜测)
控件 vs 窗体的作用域(可能原因):
setMouseTracking(true)
是控件的属性,因此它只会影响 当前控件 的事件处理。如果控件被遮挡,事件就会被拦截到上层控件,导致底层控件无法接收到鼠标移动事件。它依赖于控件的 层级顺序 和事件传递规则。setAttribute(Qt::WA_Hover)
是一种 窗体 或 控件属性,它决定了控件是否会接收悬停事件(QEvent::HoverMove
)。即使上层控件遮挡了底层控件,只要上层控件没有显式地处理悬停事件(例如没有拦截QEvent::HoverMove
),事件就会继续传递到底层控件。
事件的传递与拦截(可能原因):
setMouseTracking(true)
与QMouseEvent
是直接相关的,事件的捕获是基于控件的层级(Z 顺序)。当控件被上层控件遮挡时,上层控件拦截了事件,事件就不会传递到底层控件。setAttribute(Qt::WA_Hover)
启用的是 悬停事件,即使控件被遮挡,只要上层控件没有拦截悬停事件(QEvent::HoverMove
),事件就能继续传递到底层控件。
问题2: 多人远程操作同一台电脑,导致界面发生抢占
问题原因:
当员工A 鼠标长按 放置在界面顶部, 或者一直拖动移动, 员工B远程进来也在操作界面,会发生界面跟随员工B 的鼠标移动。 因为前者员工A 鼠标长按 Pressed 标志置位true, 后者员工B 进来虽然是悬浮移动, 但是Pressed 仍是True, 就导致界面跟随鼠标悬浮移动。
解决方法:
//鼠标 悬浮进入 或者离开 Pressed 都为false 只有按压才为true。员工B 操作的时候,检测到悬浮进入 Pressed 至为false
if (event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverLeave)
{
pressed_flag = false;
}
if (event->type() == QEvent::HoverMove)
{
QHoverEvent *hoverEvent = static_cast<QHoverEvent *>(event);
QMouseEvent mouseEvent(QEvent::MouseMove, hoverEvent->pos(),
Qt::NoButton, Qt::NoButton, Qt::NoModifier);
if (!pressed_flag)
{
CalculateBorder(mouseEvent.pos());
}
}