Python - PyQt 信号 - 发射并将参数发送到不同的类

6
这是我在这里的第二个问题,请耐心等待。我有一个包含两个类的Python脚本,其中之一管理GUI,另一个是我的“工作线程”(一个PyQt线程)。为了能够从“工作线程”更新GUI,我知道我可以设置pyqt信号并在不同点发出这些信号。在GUI线程中,我设置了连接语句,应该连接到GUI线程中的一个函数,该函数将更新GUI。
为了使此GUI更新功能知道它必须对GUI做什么,信号还发射了一个额外的参数,但在GUI线程中没有被捕获。我认为我知道这是为什么,但我无法弄清楚如何使其正常工作。
我可以包含一些代码,但有很多可能包括的部分,所以我想等待看看任何人具体要求什么部分。
希望有人能帮助我解决这个问题。
编辑:非常感谢您的回答farshed-。我应该在原始问题中加入这一点,我正在使用PyQt 4。我知道应该使用“start()”运行线程类,但当我这样做时,程序立即崩溃并停止工作。这导致我在初始化后使用“run()”来启动线程。
另外,在您的代码段中,在连接语句中直接调用updateProgressBar方法而没有直接传递任何参数,在定义该方法的括号中,只有显示该方法将接收参数。我已经尝试过这个,但它只是告诉我你希望听到的,如果你调用任何正常函数并且没有提供必要数量的参数。可能是因为我正在使用PyQt 4,也可能是因为我直接调用“run()”而不是“start()”。如果可能,希望这能帮助您进一步回答我的问题。再次,请告诉我需要包含哪些代码段。
谢谢,
BoshJailey
1个回答

15
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import time
import sys
from PyQt5.QtWidgets import QApplication, QWidget,  QProgressBar
from PyQt5.QtCore import QThread, pyqtSignal

class Thread(QThread):

    progress = pyqtSignal(int)

    def __init__(self):
        super(Thread, self).__init__()

    def __del__(self):
        self.wait()

    def run(self):
        for i in range(100):
            time.sleep(1);
            self.progress.emit(i)



class Window(QWidget):

    def __init__(self):
        super(Window, self).__init__()

        self.initUI()

    def initUI(self):
        self.progressBar = QProgressBar(self)
        self.progressBar.setValue(0)

        self.thread = Thread()
        self.thread.progress.connect(self.updateProgressBar)
        self.thread.start()


        self.setGeometry(100, 100, 200, 200)
        self.setWindowTitle("Threading in PyQt5")
        self.show()

    def updateProgressBar(self, value):
        self.progressBar.setValue(value);



if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Window()
    sys.exit(app.exec_())

让我们看看PyQt5中如何使用线程。首先,您需要创建自定义线程并从QThread继承。在普通初始化之后,您的主要逻辑应该写在run方法中,因为这是在QThread.start()(当然是在初始化之后)之后实际运行的第一个方法。因此,在编写自定义线程之后,您想要将其实现到应用程序中。为此,我们需要初始化您的自定义线程。没有什么特别的,这就像在Python中初始化任何class一样。但是,初始化线程并不意味着它开始了。您应该使它启动。要做到这一点,我们调用QThread类的start()方法。所以,我的示例仍然是使用QThread的最简单方法。我们的下一个目标是从自定义线程获取message。正如我们所看到的,首先需要确定我们的线程应该发送什么类型的消息(在我们的情况下是int)。在PyQt5中,将message称为signal,因此现在我们需要通过pyqtSignal发送我们的message。您可以看到我在我们的自定义Thread__init__之前创建了这个信号。因此,现在要发送任何signal,我们只需要调用<any_signal>.emit(<message>)方法。此外,请不要忘记将其绑定到我们主要逻辑中的某个方法。在我们的情况下,我们将其绑定到self.updateProgressBar方法。因此,在run方法的每个循环中,我们的信号都会发送到self.updateProgressBar方法。一个有点令人困惑的事情是,我们显然不需要声明self.updateProgressBar方法会获得一些参数。

self.thread.progress.connect(self.updateProgressBar)

但这仍然意味着我们的线程将发送某些信号给这个方法。我知道这有点令人困惑,我的回答显然不足以理解这个强大的工具。希望我至少可以帮助您了解基础知识。


1
最简单的例子!谢谢!基本上,我们必须为每个非阻塞任务创建一个类。 - greendino

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接