如何修复自定义QGraphicsItem的mousePressEvent坐标延迟问题?
问题根源与解决方案
首先,你的问题有两个关键原因:buttonDownScenePos()的误用,以及mouseReleaseEvent中的错误调用,我们一步步来拆解解决。
1. 先搞懂buttonDownScenePos()的真实作用
你可能误解了这个API的设计目的:它是用来返回当前事件序列中,对应按键第一次被按下时的场景坐标(比如拖拽操作里记录拖拽起始点),而不是当前点击的实时位置。
Qt会缓存这个位置,直到对应的按键被正确释放。但因为你的mouseReleaseEvent处理有错误,导致Qt内部的按键状态没有被重置,所以下一次点击时,缓存的还是上一次的位置。
2. mouseReleaseEvent里的致命笔误
看你的boardrect.cpp代码:
void BoardRect::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { QString msg = QString("release %1 %2").arg(event->buttonDownScenePos(event->button()).rx()) .arg(event->buttonDownScenePos(event->button()).ry()); qDebug( qPrintable( msg ) ); QGraphicsRectItem::mousePressEvent(event); // 这里完全错了! event->accept(); }
你在mouseReleaseEvent里调用了基类的mousePressEvent,而不是对应的mouseReleaseEvent!这会导致Qt无法正确处理按键释放的状态,缓存的按键按下位置永远不会被更新——这就是第二次点击返回旧坐标的核心原因。
修复步骤
步骤1:修正mouseReleaseEvent的基类调用
把错误的调用改成正确的基类释放事件处理:
void BoardRect::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { QString msg = QString("release %1 %2").arg(event->buttonDownScenePos(event->button()).rx()) .arg(event->buttonDownScenePos(event->button()).ry()); qDebug( qPrintable( msg ) ); QGraphicsRectItem::mouseReleaseEvent(event); // 改成这个! event->accept(); }
步骤2:在mousePressEvent中获取实时点击位置
如果你想获取当前点击的实时位置,不要用buttonDownScenePos(),直接用event->scenePos():
void BoardRect::mousePressEvent(QGraphicsSceneMouseEvent *event) { // 用scenePos()获取当前点击的实时位置 QString msg = QString("press %1 %2").arg(event->scenePos().rx()) .arg(event->scenePos().ry()); qDebug( qPrintable( msg ) ); QGraphicsRectItem::mousePressEvent(event); event->accept(); }
额外说明
如果你确实需要使用buttonDownScenePos()(比如实现拖拽功能),只要确保正确调用基类的mousePressEvent和mouseReleaseEvent,Qt就会自动维护按键位置的缓存,不会出现旧值的问题。
经过这两处修改后,你第二次及之后的点击,mousePressEvent就能正确返回当前点击的位置了,右键点击的状态也会被正确处理。
内容的提问来源于stack exchange,提问作者MangoCat
相关产品推荐
相关产品推荐

