PyQt5:如何使QThread将数据返回到主线程 [英] PyQt5: how to make QThread return data to main thread

查看:2247
本文介绍了PyQt5:如何使QThread将数据返回到主线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆