如何在函数内部的变量中使用线程? PyQt5

问题描述 投票:0回答:1

我有一个很大的函数冻结了我的PyQt5程序,我试图为此使用不同的线程(为此我使用QThread)。问题是我的函数需要一些变量才能正常工作。如何使它起作用?我展示我的所作所为。

原始代码:

class AnalysisWindow(QtWidgets.QMainWindow):

    def __init__(self, firstWindow):
        super(AnalysisWindow, self).__init__()       
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.pushButton.clicked.connect(self.letsgo)

    def letsgo(self):
        #here some code , not big
        #and at some point i have a heavy one which make it freeze until it's over:
          self.x1, self.x2, self.y1,self.y2, self.z, = self.analyze(self.i1, self.i2, self.i3)

    def analyze(self,i1,i2,i3):
        #big function
        return(x1,x2,y1,y2,z)

我尝试过的事情:

from PyQt5.QtCore import Qt, QThread, pyqtSignal


class AnalysisWindow(QtWidgets.QMainWindow):

    class MyThread(QThread):         

        _signal =pyqtSignal()
        def __init__(self):
            super().__init__()

        def run(self,i1,i2,i3):  # here I obviously can't put variables

            #I copied here my analyze function
            return(x1,x2,y1,y2,z)         

            self._signal.emit()

    def __init__(self, firstWindow):
        super(AnalysisWindow, self).__init__()       
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.pushButton.clicked.connect(self.letsgo)

    def letsgo(self):
        self.thread = MyThread()           
        self.thread.start()
        #here I dont see how to send the variables self.i1, self.i2, self.i3 and how to get the result: x1,x2,y1,y2,z

我在QMainWindow类内创建了线程类,因为我需要将一些变量(self.i1,self.i2,self.i3)从QMainWindow传递给将使用新线程的函数。也许这很糟糕,但是它根本没有用。谢谢大家。

python pyqt5 qthread
1个回答
0
投票

这是您可以采用的最小工作示例。几件事要注意:

  • 您不应该继承QThread。相反,您应该创建一个worker并将其移到您的线程中。
  • 请记住在工作函数中调用QtCore.QCoreApplication.processEvents()。否则,您的用户界面将无法响应,直到工作人员结束。
  • 在工作程序中,不是尝试return结果,而是emit保存结果的信号并在您的应用程序中处理该信号。
import sys
import random
from PyQt5.QtCore import QThread, pyqtSignal, QObject, pyqtSlot
from PyQt5 import QtWidgets
from PyQt5 import QtCore


class Analyzer(QObject):
    analyze_completed = pyqtSignal(bool)
    analyze_result = pyqtSignal(int)

    def analyze(self, x1, x2, y1, y2, z):
        self.analyze_completed.emit(False)
        from time import sleep

        # do your heavy calculations
        for i in range(10):
            QtCore.QCoreApplication.processEvents()
            sleep(0.1)
        result = x1 + x2 + y1 + y2 + z
        self.analyze_result.emit(result)
        self.analyze_completed.emit(True)


class AnalysisWindow(QtWidgets.QWidget):

    def __init__(self):
        super().__init__()
        self.label = QtWidgets.QLabel("")
        self.i = 0
        self.label_i = QtWidgets.QLabel("Value of i: {}".format(self.i))
        self.increment_button = QtWidgets.QPushButton("increment i")
        self.pushbutton = QtWidgets.QPushButton("Analyze")
        super(AnalysisWindow, self).__init__()
        self.init_UI()
        self.analyzer = Analyzer()
        self.thread = QThread()
        self.analyzer.analyze_result.connect(self.on_analyze_result_ready)
        self.analyzer.analyze_completed.connect(self.on_analyze_completed)
        self.analyzer.moveToThread(self.thread)
        self.analyze_args = []

    def init_UI(self):
        grid = QtWidgets.QGridLayout()
        grid.addWidget(self.label, 0, 0)
        grid.addWidget(self.pushbutton)
        grid.addWidget(self.label_i)
        grid.addWidget(self.increment_button)
        self.increment_button.clicked.connect(self.increment_i)
        self.pushbutton.clicked.connect(self.start_analyze)
        self.setLayout(grid)
        self.move(300, 150)
        self.setMinimumSize(300, 100)
        self.setWindowTitle('Thread Test')
        self.show()

    def start_analyze(self):
        self.analyze_args.clear()
        self.analyze_args.extend(random.choices(range(100), k=5))
        self.analyzer.analyze(*self.analyze_args)


    def increment_i(self):
        self.i += 1
        self.label_i.setText("Value of i: {}".format(self.i))

    def on_analyze_result_ready(self, result):
        self.label.setText(f"Result is {result}")

    def on_analyze_completed(self, completed):
        if completed:
            self.label.setStyleSheet('color: blue')
        else:
            self.label.setText(
                "Analyzing... {}".format(", ".join(str(i) for i in self.analyze_args)))
            self.label.setStyleSheet('color: yellow')


app = QtWidgets.QApplication(sys.argv)

widget = AnalysisWindow()

sys.exit(app.exec_())

希望这会有所帮助!

P.S:我通过查看较早的代码之一来编写此答案。经过一番研究,我意识到以前我主要是从this答案中复制了它。我觉得我应该功劳。

© www.soinside.com 2019 - 2024. All rights reserved.