我有一个很大的函数冻结了我的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传递给将使用新线程的函数。也许这很糟糕,但是它根本没有用。谢谢大家。
这是您可以采用的最小工作示例。几件事要注意:
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答案中复制了它。我觉得我应该功劳。