如何让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
相关产品推荐
相关产品推荐

