我是PyQt 5.4.1-1初学者,我的python是3.4.3。这是我的尝试,以正确的™方法跟踪many blogpostsSO问题(即没有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)之间存在区别(这是一个类属性!)

最佳答案

首先,Python是一种自动垃圾收集的语言。您的变量w超出了__init__方法的范围,并且在该方法返回后立即被垃圾回收。这就是为什么事情没有达到您第一次期望的方式的原因。将变量设为类的成员可确保在MainWindow实例存在时,它不会超出范围。

您的第二个问题很难回答,但是我敢打赌,通过查看QMetaObject文档,您将获得有关信号如何在PySide/PyQt中工作的宝贵见解。

- 编辑 -

为您的第二个问题here找到了一个更好的答案。

09-20 22:37