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

PyQt5父子QGraphicsItem悬停事件独立触发方案问询

解决QGraphicsRectItem父子项悬停事件独立与同步移动问题

问题分析

  • 悬停事件触发父项的原因:QGraphicsItem的事件默认会向上传递给父级,你的代码中调用了super().hoverEnterEvent(event)和super().hoverLeaveEvent(event),这会让事件继续传播到父项,导致父项的悬停事件被触发。
  • 子项直接加场景导致移动异常:QGraphicsItem如果设置了父项,绝对不能再手动添加到场景,父项会自动管理子项的场景归属和坐标变换。直接添加子项到场景会破坏父子间的坐标依赖,移动父项时子项的位置计算会出错。

解决方案

1. 阻止悬停事件向上传播

在子类的悬停事件处理函数中,不要调用父类的对应方法,或者调用event.accept()明确终止事件传播,这样子项的悬停事件就不会触发父项的事件。

2. 正确设置父子与场景的关系

只需要将父项添加到场景,子项通过父项的构造函数设置父关系后,会自动成为场景的一部分,无需单独调用scene.addItem()添加子项。

修改后的代码示例

import sys
from PyQt5 import QtCore, QtWidgets, QtGui

class HoverRectItem(QtWidgets.QGraphicsRectItem):
    def __init__(self, x, y, width, height,
                 parent=None,
                 fill=QtCore.Qt.blue,
                 highlight=QtCore.Qt.red,
                 name=''):
        super().__init__(x, y, width, height, parent=parent)
        self.fill_brush = QtGui.QBrush(QtGui.QColor(fill))
        self.hover_brush = QtGui.QBrush(QtGui.QColor(highlight))
        self.setBrush(self.fill_brush)
        self.name = name
        self.setAcceptHoverEvents(True) 

    def hoverEnterEvent(self, event):
        print(f"{self.name} hover enter")
        self.setBrush(self.hover_brush)
        self.update()
        # 阻止事件向上传播
        event.accept()

    def hoverLeaveEvent(self, event):
        print(f"{self.name} hover leave")
        self.setBrush(self.fill_brush)
        self.update()
        # 阻止事件向上传播
        event.accept()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    scene = QtWidgets.QGraphicsScene()

    # 创建父项并添加到场景
    central_rect = HoverRectItem(0, 0, 100, 50, parent=None, name='central')
    scene.addItem(central_rect)
    central_rect.setFlags(QtWidgets.QGraphicsItem.ItemIsMovable)
    
    # 创建子项,仅设置父关系,无需添加到场景
    input_rect = HoverRectItem(-30, 0, 20, 50, parent=central_rect, name='input')
    output_rect = HoverRectItem(110, 0, 20, 50, parent=central_rect, name='output')

    view = QtWidgets.QGraphicsView(scene)
    view.setWindowTitle("QGraphicsItem Hover Example")
    view.show()
    app.exec_()

关键改动说明

  • 移除了悬停事件中的super()调用,改用event.accept()终止事件传播,确保子项悬停不会触发父项的对应事件,实现悬停独立。
  • 删除了子项的scene.addItem()调用,子项通过父子关系自动加入场景,保证父项移动时子项的坐标变换完全同步,解决运动状态异常问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 06:44:51