如何阻止信号直到所有其他信号都被处理?

2024-05-19 05:21:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在开发一个Qt小部件,它提供了一个图形网格(每一个都是一个QWidget)。我想在我所有的绘图上同步“keepspectratio”策略。在

如果我调用它的setKeepDataAspectRatio(bool)方法,每个单独的绘图都将发出sigKeepAspectRatioChanged信号,该方法在网格中广播策略(True或{})及其(row, column)坐标。在

我的复合小部件监听它的所有绘图,当其中一个更改了它的纵横比策略(单击工具按钮),它需要将其传播到所有其他绘图。在

这是我所尝试的,但它会导致无穷多的RuntimeError: maximum recursion depth exceeded in 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. _plots),dict键是(r, c)坐标元组。在


Tags: 方法inselftrue网格绘图plot部件
2条回答

我找到了一个可行的解决方案,但它可能不是最有效的:我断开所有单个信号,然后在设置所有策略后重新连接。在

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

这当然可以用一个装饰器包装:

^{pr2}$

以及来自this blog post的装饰师:

^{3}$

相关问题 更多 >

    热门问题