QGraphicsScene调用blockSignals后selectionChanged仍触发的解决方案
PyQt5 QGraphicsScene selectionChanged 槽函数递归触发通用解决方案
你遇到的问题本质是槽函数内部修改选中状态的操作,再次触发了同一个selectionChanged信号,导致槽函数递归执行。以下是两种通用、可复用于所有同类信号槽递归场景的解决方案:
方案1:重入标志位(全版本兼容)
通过自定义布尔标志位标记槽函数的执行状态,从逻辑上拦截递归调用,兼容性最好,支持所有PyQt5版本。
实现步骤:
- 类初始化时新增一个私有布尔属性
_in_selection_slot,默认值为False - 进入槽函数时先判断标志位:如果为
True说明是递归调用,直接返回 - 标记标志位为
True后执行业务逻辑,用try...finally保证标志位最终一定会被复位
代码示例:
class Template(QMainWindow): def __init__(self): super().__init__() self._in_selection_slot = False # 新增重入标志位 self.scene = QGraphicsScene(0, 0, 200, 400) c = self.scene.addEllipse(8, 8, 34, 34, Qt.black, Qt.black) c.setPos(0, 350) c.setFlag(QGraphicsItem.ItemIsSelectable) self.scene.selectionChanged.connect(self.move) view = QGraphicsView(self.scene) view.setRenderHint(QPainter.Antialiasing) self.setCentralWidget(view) def move(self): # 递归调用直接拦截 if self._in_selection_slot: return # 标记进入槽函数 self._in_selection_slot = True try: # 原有业务逻辑完全不用改 selected = self.scene.selectedItems() if selected: selected[0].moveBy(0, -50) selected[0].setSelected(False) finally: # 无论是否出现异常,最终复位标志位 self._in_selection_slot = False
适用场景:
所有需要避免槽函数递归调用的场景,不需要关心信号发射源,哪怕逻辑中会触发多个对象的多个信号都可以正常拦截。
方案2:QSignalBlocker(Qt 5.7+ 适用)
Qt内置的RAII工具类,创建时自动阻塞指定对象的所有信号,对象销毁时自动恢复信号状态,不需要手动调用blockSignals,避免手动操作遗漏导致的信号永久阻塞问题。
代码示例:
import sys from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * class Template(QMainWindow): def __init__(self): super().__init__() self.scene = QGraphicsScene(0, 0, 200, 400) c = self.scene.addEllipse(8, 8, 34, 34, Qt.black, Qt.black) c.setPos(0, 350) c.setFlag(QGraphicsItem.ItemIsSelectable) self.scene.selectionChanged.connect(self.move) view = QGraphicsView(self.scene) view.setRenderHint(QPainter.Antialiasing) self.setCentralWidget(view) def move(self): selected = self.scene.selectedItems() if selected: selected[0].moveBy(0, -50) # 阻塞scene的所有信号,当前作用域结束后自动恢复 blocker = QSignalBlocker(self.scene) selected[0].setSelected(False)
适用场景:
明确知道信号发射源的场景,代码更简洁,不需要维护额外的状态变量。
内容的提问来源于stack exchange,提问作者alec
相关产品推荐
相关产品推荐

