Python 如何在处理所有其他信号之前阻止信号?
我正在开发一个Qt小部件,它提供了一个网格图(每个图都是一个QWidget)。我想在我的所有绘图上同步“keepAspectRatio”策略 如果调用其Python 如何在处理所有其他信号之前阻止信号?,python,qt,pyqt,Python,Qt,Pyqt,我正在开发一个Qt小部件,它提供了一个网格图(每个图都是一个QWidget)。我想在我的所有绘图上同步“keepAspectRatio”策略 如果调用其setKeepDataAspectRatio(bool)方法,则每个单独的绘图将发出sigkeepasspectratiochanged信号,该方法在网格中广播策略(True或False)及其(行、列)坐标 我的复合小部件将侦听其所有绘图,当其中一个更改其纵横比策略时(单击工具按钮),它需要将其传播到所有其他绘图 这是我尝试过的,但它会导致无限多
setKeepDataAspectRatio(bool)
方法,则每个单独的绘图将发出sigkeepasspectratiochanged
信号,该方法在网格中广播策略(True
或False
)及其(行、列)
坐标
我的复合小部件将侦听其所有绘图,当其中一个更改其纵横比策略时(单击工具按钮),它需要将其传播到所有其他绘图
这是我尝试过的,但它会导致无限多的RuntimeError:cmp中超过最大递归深度的错误:
def _onKeepAspectRatioChanged(self, isKeepAspectRatio, row, col):
"""If any plot changes its keepAspectRatio policy,
apply it to all other plots."""
print("received sigKeepAspectRatioChanged from plot %d, %d" % (row, col))
self.blockSignals(True)
for r, c in self._plots:
if not (r, c) == (row, col):
self._plots[(r, c)].plot.setKeepDataAspectRatio(isKeepAspectRatio)
qt.QApplication.instance().processEvents()
self.blockSignals(False)
关于如何正确地做到这一点,有什么想法吗
顺便说一句,对每个单独绘图的引用保存在字典中(self.\u plots
),dict键是(r,c)
坐标元组。我找到了一个可行的解决方案,但它可能不是最有效的:我断开所有单独信号,然后在设置所有策略后重新连接
def _onKeepAspectRatioChanged(self, isKeepAspectRatio, row, col):
with self._disconnectAllAspectRatioSignals():
for r, c in self._plots:
self._plots[(r, c)].plot.setKeepDataAspectRatio(isKeepAspectRatio)
@contextlib.contextmanager
def _disconnectAllAspectRatioSignals(self):
for r, c in self._plots:
self._plots[(r, c)].sigKeepAspectRatioChanged.disconnect(
self._onKeepAspectRatioChanged)
yield
for r, c in self._plots:
self._plots[(r, c)].sigKeepAspectRatioChanged.connect(
self._onKeepAspectRatioChanged)
我找到了一个可行的解决方案,但它可能不是最有效的:我断开所有单个信号的连接,然后在设置所有策略后重新连接
def _onKeepAspectRatioChanged(self, isKeepAspectRatio, row, col):
with self._disconnectAllAspectRatioSignals():
for r, c in self._plots:
self._plots[(r, c)].plot.setKeepDataAspectRatio(isKeepAspectRatio)
@contextlib.contextmanager
def _disconnectAllAspectRatioSignals(self):
for r, c in self._plots:
self._plots[(r, c)].sigKeepAspectRatioChanged.disconnect(
self._onKeepAspectRatioChanged)
yield
for r, c in self._plots:
self._plots[(r, c)].sigKeepAspectRatioChanged.connect(
self._onKeepAspectRatioChanged)
您真正关心的是不重新输入该方法。信号和插槽只是它发生的管道。因此:保护相关方法不受递归的影响。它比断开和恢复信号插槽连接的效率高出一个数量级以上。基本上:
def _method(self, ...):
if self.in_method:
return
try:
self.in_method = True
...
finally:
self.in_method = False
这当然可以用装饰器包装:
@norecursion
def _onKeepAspectRatioChanged(self, isKeepAspectRatio, row, col):
...
还有来自:
您真正关心的是不重新输入该方法。信号和插槽只是它发生的管道。因此:保护相关方法不受递归的影响。它比断开和恢复信号插槽连接的效率高出一个数量级以上。基本上:
def _method(self, ...):
if self.in_method:
return
try:
self.in_method = True
...
finally:
self.in_method = False
这当然可以用装饰器包装:
@norecursion
def _onKeepAspectRatioChanged(self, isKeepAspectRatio, row, col):
...
还有来自:
您需要做的是在实际发出信号的小部件上使用blockSignals
(即self.\u plots[(r,c)]
)。在self
上调用它没有意义,因为到那时已经太晚了。你需要做的是在实际发出信号的小部件上使用blockSignals
(即self.\u plots[(r,c)]
)。在self上调用它是没有意义的,因为到那时已经太晚了。