You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:24:48