gpt4 book ai didi

python - PyQt:将信号连接到插槽以启动后台操作

转载 作者:太空狗 更新时间:2023-10-29 20:20:14 29 4
gpt4 key购买 nike

我有以下代码执行后台操作 (scan_value),同时更新 ui 中的进度条 (progress)。 scan_value 迭代 obj 中的某个值,每次更改值时都会发出一个信号 (value_changed)。由于此处不相关的原因,我必须将其包装在另一个线程中的对象 (Scanner) 中。当按钮 scanclicked 时,将调用 Scanner。我的问题来了……以下代码工作正常(即进度条按时更新)。

# I am copying only the relevant code here.

def update_progress_bar(new, old):
fraction = (new - start) / (stop - start)
progress.setValue(fraction * 100)

obj.value_changed.connect(update_progress_bar)

class Scanner(QObject):

def scan(self):
scan_value(start, stop, step)
progress.setValue(100)

thread = QThread()
scanner = Scanner()
scanner.moveToThread(thread)
thread.start()

scan.clicked.connect(scanner.scan)

但如果我将最后一部分更改为:

thread = QThread()
scanner = Scanner()
scan.clicked.connect(scanner.scan) # This was at the end!
scanner.moveToThread(thread)
thread.start()

进度条只在结束时更新(我猜一切都在同一个线程上运行)。如果我在将对象接收对象移动到线程之前或之后将信号连接到插槽是否无关紧要。

最佳答案

连接是在将工作对象移动到另一个线程之前还是之后建立的并不重要。引用自Qt docs :

Qt::AutoConnection - If the signal is emitted from a differentthread than the receiving object, the signal is queued, behaving asQt::QueuedConnection. Otherwise, the slot is invoked directly,behaving as Qt::DirectConnection. The type of connection isdetermined when the signal is emitted. [emphasis added]

因此,只要将 connecttype 参数设置为 QtCore.Qt.AutoConnection(默认),Qt应确保以适当的方式发出信号。

信号相比,示例代码的问题更有可能是插槽。信号连接到的 python 方法可能需要标记为 Qt 插槽,使用 pyqtSlot decorator :

from QtCore import pyqtSlot

class Scanner(QObject):

@pyqtSlot()
def scan(self):
scan_value(start, stop, step)
progress.setValue(100)

编辑:

应该澄清的是,只有在相当新的 Qt 版本中,连接类型才会在发出信号时确定。此行为是在 4.4 版中引入的(以及 Qt 多线程支持中的其他几项更改)。

此外,可能值得进一步扩展 PyQt 特定问题。在 PyQt 中,信号可以连接到 Qt 插槽、另一个信号或任何 Python 可调用函数(包括 lambda 函数)。对于后一种情况,会在内部创建一个代理对象,它包装 python 可调用对象并提供 Qt 信号/槽机制所需的槽。

正是这个代理对象导致了问题。创建代理后,PyQt 将简单地执行此操作:

    if (rx_qobj)
proxy->moveToThread(rx_qobj->thread());

如果在接收对象(即 rx_qobj)移动到其线程后 建立连接,这很好;但如果它在之前创建,代理将留在主线程中。

使用 @pyqtSlot 装饰器完全避免了这个问题,因为它更直接地创建了一个 Qt 槽并且根本不使用代理对象。

最后,还需要注意的是,这个问题目前不影响 PySide。

关于python - PyQt:将信号连接到插槽以启动后台操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20752154/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com