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

如何让QGraphicsEllipseItem与QGraphicsScene的mouseMoveEvent同时生效

问题:QGraphicsEllipseItem与QGraphicsScene的mouseMoveEvent无法同时触发?

我自定义了QGraphicsEllipseItem和QGraphicsScene类,两者均重写了mouseMoveEvent与mousePressEvent方法。但目前仅QGraphicsScene的mouseMoveEvent能够生效,推测是场景的事件覆盖了图元的事件,不过mousePressEvent却可以同时触发。请问有什么办法能让两者的mouseMoveEvent都正常工作?

from PyQt5.QtWidgets import *


class CustomEllipseItem(QGraphicsEllipseItem):
    def __init__(self, *args, **kwargs):
        super(CustomEllipseItem, self).__init__(*args, **kwargs)

    def mousePressEvent(self, event):
        print("EllipseItem mousePressEvent")
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        print("EllipseItem mouseMoveEvent")
        super().mouseMoveEvent(event)


class CustomScene(QGraphicsScene):
    def __init__(self, *args, **kwargs):
        super(CustomScene, self).__init__(*args, **kwargs)

    def mousePressEvent(self, event):
        print("Scene mousePressEvent")
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        print("Scene mouseMoveEvent")
        super().mouseMoveEvent(event)

if __name__ == '__main__':
    app = QApplication([])

    scene = CustomScene()
    view = QGraphicsView(scene)

    ellipse_item = CustomEllipseItem(0, 0, 100, 100)
    scene.addItem(ellipse_item)

    view.show()

    app.exec_()

原因分析

QGraphicsItem和QGraphicsScene的鼠标事件触发逻辑存在差异:

  • QGraphicsScene的mouseMoveEvent:只要鼠标在场景范围内移动,无论是否按下鼠标,都会触发。
  • QGraphicsItem的mouseMoveEvent:仅当图元捕获到鼠标(即鼠标按下在该图元上)后,拖动鼠标时才会触发。单纯鼠标在图元上移动但未按下,不会触发它的mouseMoveEvent。

解决办法

根据你的需求场景,选择对应的方案:

场景1:需要鼠标悬停在图元上移动(不按下)时触发图元的事件

给CustomEllipseItem开启悬停事件接收,并重写hoverMoveEvent(专门处理悬停移动的事件):

class CustomEllipseItem(QGraphicsEllipseItem):
    def __init__(self, *args, **kwargs):
        super(CustomEllipseItem, self).__init__(*args, **kwargs)
        self.setAcceptHoverEvents(True)  # 开启悬停事件支持

    def mousePressEvent(self, event):
        print("EllipseItem mousePressEvent")
        super().mousePressEvent(event)

    def mouseMoveEvent(self, event):
        print("EllipseItem mouseMoveEvent")
        super().mouseMoveEvent(event)

    def hoverMoveEvent(self, event):
        print("EllipseItem hoverMoveEvent")  # 悬停移动时触发
        super().hoverMoveEvent(event)

修改后,鼠标在椭圆上移动(未按下)时,会触发图元的hoverMoveEvent,同时场景的mouseMoveEvent也会正常触发。

场景2:仅需要按下鼠标拖动图元时触发图元的mouseMoveEvent

你的现有代码已经满足这个逻辑,只需按下鼠标在椭圆上,然后拖动鼠标,此时图元的mouseMoveEvent就会触发,同时场景的mouseMoveEvent也会正常执行。

注意:确保图元和场景的事件方法中都调用了super(),这样事件才能正常传递——你的代码里已经做到了这一点。


内容的提问来源于stack exchange,提问作者Vlad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 10:52:29