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

2024-10-04 07:32:47 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个冻结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类中创建了thread类,因为我需要将一些变量(self.i1、self.i2、self.i3)从QMainWindow传递给将使用新线程的函数。也许这很糟糕,但它根本不起作用。谢谢大家


Tags: selfuihereinitdefx1x2i3
1条回答
网友
1楼 · 发布于 2024-10-04 07:32:47

下面是一个简单的工作示例,您可以根据自己的代码对其进行调整。 需要注意的几件事:

  • 您不应该从QThread继承。相反,您应该创建一个辅助线程并将其移动到线程中
  • 在worker中,不是试图return一个结果,而是emit保存结果的信号,并在应用程序中处理该信号
  • 类似地,与其尝试正常调用您的工作程序,不如通过QtCore.QMetaObject.invokeMethod通过其插槽与它通信。一旦线程启动,您可以任意调用此方法

更多信息,请参阅this答案

import sys
import random
from PyQt5.QtCore import QThread, pyqtSignal, QObject, pyqtSlot, Qt
from PyQt5 import QtWidgets
from PyQt5 import QtCore


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

    @pyqtSlot(str, list)
    def analyze(self, foo, analyze_args):
        print(foo, analyze_args)
        self.analyze_completed.emit(False)

        # do your heavy calculations
        for i in range(10000000):
            x = i ** 0.5

        result = sum(analyze_args)
        self.analyze_result.emit(analyze_args, 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.analyze_args = []
        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.thread.start()
        self.init_UI()

    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))
        QtCore.QMetaObject.invokeMethod(self.analyzer, 'analyze', Qt.QueuedConnection,
                                        QtCore.Q_ARG(str, "Hello World!"),
                                        QtCore.Q_ARG(list, 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, args, result):
        t = "+".join(str(i) for i in args)
        self.label.setText(f"{t} = {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_())


希望这有帮助

相关问题 更多 >