Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在处理所有其他信号之前阻止信号?_Python_Qt_Pyqt - Fatal编程技术网

Python 如何在处理所有其他信号之前阻止信号?

Python 如何在处理所有其他信号之前阻止信号?,python,qt,pyqt,Python,Qt,Pyqt,我正在开发一个Qt小部件,它提供了一个网格图(每个图都是一个QWidget)。我想在我的所有绘图上同步“keepAspectRatio”策略 如果调用其setKeepDataAspectRatio(bool)方法,则每个单独的绘图将发出sigkeepasspectratiochanged信号,该方法在网格中广播策略(True或False)及其(行、列)坐标 我的复合小部件将侦听其所有绘图,当其中一个更改其纵横比策略时(单击工具按钮),它需要将其传播到所有其他绘图 这是我尝试过的,但它会导致无限多

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

如果调用其
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上调用它是没有意义的,因为到那时已经太晚了。