PyQt5:如何使QThread将数据返回到主线程 [英] PyQt5: how to make QThread return data to main thread
问题描述
我是PyQt 5.4.1-1
初学者,我的python是3.4.3
.这是我尝试遵循 blogposts 和
I am a PyQt 5.4.1-1
beginner, my python is 3.4.3
. Here is my attempt to follow the many blogposts and SO questions on the proper ™ way to make a thread (i.e. no QThread subclassing):
#!/usr/bin/env python3
from PyQt5.QtCore import QObject, QThread
from PyQt5.QtCore import pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QMainWindow
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
print("Base init")
self.thread = QThread()
w = Worker()
w.finished[int].connect(self.onFinished)
w.moveToThread(self.thread)
self.thread.started.connect(w.work)
self.thread.start()
@pyqtSlot(int)
def onFinished(self, i):
print("Base caught finished, {}".format(i))
class Worker(QObject):
finished = pyqtSignal(int)
def __init__(self):
print("Worker init")
super().__init__()
def work(self):
print("Worker work")
Worker.finished.emit(42)
if __name__ == "__main__":
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
mw = MainWindow()
mw.show()
sys.exit(app.exec_())
在撰写此问题时,我意识到,如果进行了以下更改,那么一切似乎都有效:
While writing this question, I realised that if the following changes are made, then it all seems to work:
...
self.w = Worker()
self.w.finished[int].connect(self.onFinished)
self.w.moveToThread(self.thread)
self.thread.started.connect(self.w.work)
...
...
self.finished.emit(42)
...
但是我不明白为什么这会有所帮助.为什么我必须使与Gui无关的Worker
实例成为Gui类的成员?坦率地说,感觉不对.现在,关于信号:这是一个 class属性那么为什么调用Worker.finished.emit(42)
会在运行时失败,而self.finisehd.emit(42)
却会在我期望没有区别的时候成功(这是一个类属性!)有什么区别?
But I do not understand why this helps. Why do I have to make a non-Gui related Worker
instance a member of the Gui class? Feels wrong, frankly. And now about the signal: it's a class attribute so why is there a difference between calling Worker.finished.emit(42)
which fails at runtime and a self.finisehd.emit(42)
which succeeds when I would expect no difference (it's a class attribute!)
推荐答案
首先,Python是一种自动垃圾收集的语言.您的变量w
在__init__
方法中超出范围,并且在该方法返回后立即被垃圾回收.这就是为什么事情没有达到您第一次期望的方式的原因.将变量设为类的成员可确保在MainWindow
实例存在时,变量不会超出范围.
First, Python is an automatically garbage collected language. Your variable w
goes out of scope in the __init__
method, and is promptly garbage collected after the method returns. This is why things did not work out the way you expected the first time. Making the variable a member of the class makes sure that it does not go out of scope while the MainWindow
instance exists.
Your second question is a bit harder to answer, but I bet you will gain valuable insight into how signals work in PySide/PyQt by looking at the QMetaObject documentation.
-编辑-
Found a better answer for your second question here.
这篇关于PyQt5:如何使QThread将数据返回到主线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!