Qt中鼠标悬停输入线名称显示错误及范围异常问题
逻辑门输入线悬停Tooltip异常问题修复方案
问题描述
我基于QGraphicsScene实现了包含AND、OR、NOR等数字逻辑门的可视化场景,逻辑门由Arc、Polyline、Circle、直线等图形元素构成。需求是:鼠标悬停在门的输入线上时,Tooltip显示对应输入线的名称。
但实际测试出现两个问题:
- 触发范围不符合预期:以截图中的i2门为例,顶部输入线对应名称a[2],底部对应a[3],但鼠标悬停在红线内时显示a[3],悬停在红线外、蓝线内区域时显示a[2],并非只有悬停在输入线本体上才触发Tooltip。
- 名称显示错误:Tooltip展示的输入线名称和实际悬停的线条不匹配。
当前相关代码
myViewer类的eventFilter实现
bool myViewer::eventFilter(QObject* watched, QEvent* event) { case QEvent::MouseMove: { QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event); QPointF mousePoint = _view->mapToScene(mouseEvent->pos()); QGraphicsItem* SelectedItem = scene->itemAt(mousePoint, QTransform()); if(SelectedItem) { myPoly* item = qgraphicsitem_cast<myPoly*>(SelectedItem); if(item) { item->setToolTip(item->GetPolyLineName()); // GetPolyLineName返回a[2]或a[3] } } } break; }
myPoly类头文件(myPoly.h)
class myPoly : public QGraphicsPathItem { public: QString &GetPolyLineName(); };
问题排查与修复建议
1. 解决Tooltip触发范围错误
当前使用scene->itemAt()获取鼠标下的元素,而默认QGraphicsPathItem的碰撞检测范围是路径的填充区域(如果是线条,填充区域会包含线条周围的扩展区域),导致鼠标没碰到线条本体也触发了Tooltip。
修复步骤:
- 给
myPoly设置精确的碰撞形状,仅检测线条本身的区域:
在myPoly的构造函数中,基于线条宽度生成碰撞路径:myPoly::myPoly() { setAcceptHoverEvents(true); // 开启hover事件支持 // 根据绘制时的线条宽度生成碰撞路径 QPainterPathStroker stroker; stroker.setWidth(2); // 这里设置你绘制输入线时使用的线条宽度 QPainterPath collisionPath = stroker.createStroke(path()); setShape(collisionPath); // 设置自定义碰撞形状 }
2. 修复名称显示错误
- 首先检查
GetPolyLineName()的实现,确认每个myPoly实例的名称是否正确绑定到对应的输入线(比如i2门的顶部线条是否确实赋值了a[2],底部线条赋值a[3])。 - 检查图形元素的层级:如果输入线存在重叠,
scene->itemAt()会返回最上层的元素,可能导致鼠标实际悬停的是下层线条,但触发了上层的Tooltip。可以通过setZValue()调整输入线的层级,确保每条输入线的层级正确。
3. 优化Tooltip触发逻辑
不要在MouseMove事件中频繁设置Tooltip,建议在myPoly类内部处理hover事件,这样更精准高效:
修改myPoly.h:
class myPoly : public QGraphicsPathItem { public: QString &GetPolyLineName(); protected: void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; };
实现hover事件:
void myPoly::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { setToolTip(GetPolyLineName()); QGraphicsPathItem::hoverEnterEvent(event); } void myPoly::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { setToolTip(""); // 离开时清空Tooltip QGraphicsPathItem::hoverLeaveEvent(event); }
这样只有鼠标真正进入输入线的碰撞区域时才显示Tooltip,离开时自动隐藏,避免了MouseMove事件中的频繁判断。
内容的提问来源于stack exchange,提问作者tushar
相关产品推荐
相关产品推荐

