我有以下代码在更新UI中的进度条(progress
)时执行后台操作(scan_value
)。 scan_value
迭代了obj
中的某个值,每次更改该值时都会发出一个信号(value_changed
)。由于这里不相关的原因,我必须在另一个线程中将其包装在一个对象(Scanner
)中。扫描仪在按钮scan
是clicked
时被调用。我的问题来了......以下代码正常工作(即进度条按时更新)。PyQt:将信号连接到插槽以启动后台操作
# 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()
进度栏得到仅在结束时更新(我的猜测是,一切都在同一线程上运行)。如果在将对象接收对象移动到线程之前将信号连接到一个插槽之前,它应该是无关紧要的。
看起来像ekhumoro是正确的(pyqt/qt似乎没有正确地自动检测连接类型,除非你用@pyqtSlot()明确地修饰你的插槽)。但是,我想指出'progress.setValue(100)'这一行是线程**不安全**,因为您正在从主线程以外的线程访问Qt GUI对象。其余的发布代码在Qt GUI操作 –
@three_pineapples方面是线程安全的。知道这里是否存在PyQt错误,或者PyQt如何连接Python可调参数,这将是很有趣的。我知道当不使用'@ pyqtSlot'时会创建某种代理对象,但是对于排队连接究竟会产生什么后果,我不知道。 – ekhumoro
@ekhumoro我认为这可能是一个PyQt4错误,或者至少应该纠正一个缺陷。它当然不会在PySide中显示出相同的行为(PySide总是在QThread中运行'scan'函数,而不管信号的位置或插槽的位置如何)。我在这里http://pastebin.com/SqP3WM1z做了一个简单的例子,它列出了正在运行的线程。 –