我是PyQt 5.4.1-1
初学者,我的python是3.4.3
。以下是我尝试按照正确的™方式关注many blogposts和SO问题制作线程(即没有QThread子类化):
#!/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_())
在写这个问题时,我意识到如果做出以下更改,那么一切似乎都有效:
...
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 attribute那么为什么在运行时失败的Worker.finished.emit(42)
调用与我预期没有差异的self.finisehd.emit(42)
成功之间存在差异(&& #39; sa class属性!)
答案 0 :(得分:1)
首先,Python是一种自动垃圾收集语言。您的变量w
超出了__init__
方法的范围,并在方法返回后立即进行垃圾回收。这就是为什么事情没有像你预期的那样第一次发挥作用的原因。使变量成为类的成员可确保在MainWindow
实例存在时它不会超出范围。
你的第二个问题有点难以回答,但我敢打赌,通过查看QMetaObject文档,你将获得有关PySide / PyQt中信号如何工作的宝贵见解。
- 编辑 -
为您的第二个问题here找到了更好的答案。