如何在禁用 table 后阻止 QTableWidget 信号?

How can I block QTableWidget signals after disabling the table?

我有一个 python QTableWidget 填充了 4 列。选择任何列运行 qTableWidget.cellClicked() 信号,然后突出显示整行,并运行一堆代码。

self._qTableWidget.cellClicked.connect(self.cellClicked)

def cellClicked(self, row, column):
   """
      Handle cell clicked signal.
   """
   self._qTableWidget.setDisabled(True)
   qTableWidgetItem = self._qTableWidget.item(row, column)
   if qTableWidgetItem is None:
      return
   else:
      # ***RUNS SOME CODE***
      pass
   self._qTableWidget.setEnabled(True)

在代码中,我想在代码运行之前禁用 QTableWidget 接受任何点击,然后启用 QTableWidget(我已尝试使用 setDisabled()/setEnabled())。

但是,如果您单击一个单元格,table 将被正确禁用,但您仍然可以单击 table 中的单元格。当 table 再次启用时,它会在您单击的 QTableWidgetItem 上再次运行 cellClicked() 信号,而 table 被禁用。

我试过使用以下方法:

self._qTableWidget.blockSignals(True)
self._qTableWidget.blockSignals(False)
self._qTableWidget.cellClicked.disconnect(self.cellClicked)
self._qTableWidget.cellClicked.connect(self.cellClicked)
self.setAllCellItemFlags(QtCore.Qt.NoItemFlags)

def setAllCellItemFlags(self, flag):
   """
      Sets all QTableWidgetItem flags
   """
   for row in range(self._qTableWidget.rowCount()):
      for column in range(self._qTableWidget.columnCount()):
         qTableWidgetItem = self._qTableWidget.item(row, column)
         qTableWidgetItem.setFlags(flag)

这就是您的代码中可能发生的情况:

  1. 第一次点击到达并发出信号
  2. 在连接的插槽中禁用(或断开)信号
  3. 你开始你的代码,当它运行正在运行时它会阻塞主线程中的事件循环
  4. 同时另一个鼠标点击出现,它创建了鼠标点击事件,但它被放入等待队列等待事件循环能够处理它
  5. 一段时间后,您的冗长代码完成,您 re-enable(或 re-connect)发出信号
  6. 事件循环解除阻塞并处理等待的鼠标事件
  7. 作为对点击事件的响应,发出另一个信号并且连接的插槽再次获得 运行,即转到第 2 步...

如您所见,第二次点击在信号获得 re-enabled 后得到处理。这是您问题的根本原因。您需要做的是 re-enable 事件循环处理等待的鼠标点击(或鼠标点击)后的信号。

最简单的解决方案是在 re-enable 信号之前调用 QApplication.processEvents(QEventLoop.AllEvents, 0)。这将导致所有点击事件被处理,即被忽略,因为此时信号仍将被禁用。请阅读有关处理还发布(尚未排队)事件的方法的此重载的文档。与没有 ms 参数的其他重载相反,它只处理已经排队的事件。如果值 0 不够,则尝试更长的时间延迟,例如100 毫秒