You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

QGraphicsItem/QGraphicsWidget鼠标进入时发射信号的最佳实现方案

解决QGraphicsItem悬停触发MainWindow更新的方案

这个问题我之前也碰到过,核心就是给你的Square类补上信号发射的能力——毕竟QGraphicsItem本身确实不是为发射信号设计的,但我们可以通过继承QObject来扩展它的功能,具体步骤如下:

  • 让Square类支持信号槽机制
    你可以让Square同时继承QObjectQGraphicsItem(注意继承顺序,QObject要放在前面),或者直接使用QGraphicsObject(它本身就是QObjectQGraphicsItem的子类,更省心)。

  • 声明自定义悬停信号
    Square类中添加一个自定义信号,比如hovered(),用来通知主窗口鼠标已经悬停在这个项目上。

  • 重写hoverEnterEvent并发射信号
    重写hoverEnterEvent方法,在里面先调用父类的实现(保证原有逻辑正常运行),然后发射我们定义的信号。别忘了要给Square设置setAcceptHoverEvents(True),不然悬停事件根本不会触发。

  • 在MainWindow中连接信号与槽
    当你创建Square实例后,把它的hovered()信号连接到MainWindowupdate()槽上就行。

代码示例

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

火山引擎 最新活动