QGraphicsItem/QGraphicsWidget鼠标进入时发射信号的最佳实现方案
解决QGraphicsItem悬停触发MainWindow更新的方案
这个问题我之前也碰到过,核心就是给你的Square类补上信号发射的能力——毕竟QGraphicsItem本身确实不是为发射信号设计的,但我们可以通过继承QObject来扩展它的功能,具体步骤如下:
让Square类支持信号槽机制:
你可以让Square同时继承QObject和QGraphicsItem(注意继承顺序,QObject要放在前面),或者直接使用QGraphicsObject(它本身就是QObject和QGraphicsItem的子类,更省心)。声明自定义悬停信号:
在Square类中添加一个自定义信号,比如hovered(),用来通知主窗口鼠标已经悬停在这个项目上。重写hoverEnterEvent并发射信号:
重写hoverEnterEvent方法,在里面先调用父类的实现(保证原有逻辑正常运行),然后发射我们定义的信号。别忘了要给Square设置setAcceptHoverEvents(True),不然悬停事件根本不会触发。在MainWindow中连接信号与槽:
当你创建Square实例后,把它的hovered()信号连接到MainWindow的update()槽上就行。
代码示例
Square类的定义
from PyQt5.QtWidgets import QGraphicsItem, QObject from PyQt5.QtCore import pyqtSignal, QRectF # 或者直接继承QGraphicsObject,省去多继承的麻烦 class Square(QObject, QGraphicsItem): hovered = pyqtSignal() # 自定义悬停信号 def __init__(self, parent=None): super().__init__(parent) self.setAcceptHoverEvents(True) # 必须启用悬停事件接受 def hoverEnterEvent(self, event): super().hoverEnterEvent(event) # 保留父类的默认悬停行为 self.hovered.emit() # 发射信号通知主窗口 # 实现QGraphicsItem必须的两个方法 def boundingRect(self): # 根据你的需求返回项目的边界矩形 return QRectF(0, 0, 50, 50) def paint(self, painter, option, widget): # 绘制正方形的逻辑 painter.drawRect(self.boundingRect())
MainWindow中的信号连接
from PyQt5.QtWidgets import MainWindow, QGraphicsScene, QGraphicsView class MainWindow(MainWindow): def __init__(self): super().__init__() self.scene = QGraphicsScene() self.view = QGraphicsView(self.scene) self.setCentralWidget(self.view) # 创建Square实例并添加到场景 self.square_item = Square() self.scene.addItem(self.square_item) # 连接信号与槽:当Square被悬停时触发MainWindow的update self.square_item.hovered.connect(self.update) def update(self): # 这里写你需要执行的更新逻辑 print("MainWindow更新已触发!")
这样设置后,当鼠标悬停在Square项目上时,hoverEnterEvent就会发射信号,进而触发MainWindow.update的调用啦~
内容的提问来源于stack exchange,提问作者Carel




