Python - PyQt信号 - 向不同的类发送和发送参数

时间:2016-10-08 14:31:46

标签: python multithreading signals-slots

这只是我的第二个问题所以请耐心等待我。我有一个python脚本,目前包含两个类。其中一个管理GUI,另一个是我的'工作线程'(pyqt线程)。为了让我能够从'工作线程'更新GUI,我知道我可以设置pyqt信号并在不同的点发出它们。回到GUI线程我设置了connect语句,它应该连接到GUI线程中的一个函数,该函数将更新GUI。

为了让这个GUI更新功能知道它与GUI有什么关系,信号也会发出额外的参数,但这不会在GUI线程中被选中。我想我知道为什么会这样,但我无法弄清楚如何让它正常工作。

我会包含一些代码,但有很多可能的部分可以包含在内,我想我会等着看看有什么特别的要求。

我希望有人能帮助我。

编辑:感谢您的回答 - 。我应该把它放在最初的问题中,我使用的是PyQt 4.我知道线程类应该使用'start()'来运行,但是当我这样做时,程序会立即崩溃并停止工作。这导致我在初始化之后使用'run()'来启动线程。

此外,在您的代码段中调用updateProgressBar方法而不直接在connect语句中传递任何参数,并且仅在定义方法的括号内,是否显示该方法将接收参数。我已经尝试了这个,但它只是告诉我,如果你调用任何正常的函数而不提供必要数量的参数,你会期望听到什么。可能这是因为我使用PyQt 4或者可能是因为我直接调用'run()'而不是'start()'。希望这可以帮助您在可能的情况下进一步回答我的问题。如果您希望我包含任何代码段,请再次提及。

谢谢,

BoshJailey

1 个答案:

答案 0 :(得分:5)

#!/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,所以现在我们要通过message发送pyqtSignal。您可以在我们的自定义__init__中查看我在Thread之前创建此信号的方式。现在要发送任何signal,我们只需要调用<any_signal>.emit(<message>)方法。而且不要忘记用我们主要逻辑中的某些方法绑定它。在我们的例子中,我们将它绑定到self.updateProgressBar方法。因此,在run方法的每个循环中,我们的信号都会发送到self.updateProgressBar方法。有点令人困惑的是,我们不必明确声明self.updateProgressBar方法将获得一些参数

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

但这仍然意味着我们的线程将向此方法发送一些信号。我知道这有点令人困惑,我的答案显然不足以理解这个强大的工具。希望我能帮助你至少获得基础知识。