Я без особой удачи пытался заставить это работать, и я исключаю все ненужные вещи. Я основывал это на этом примере здесь. https://www.learnpyqt.com/courses/concurrent-execution/multithreading-pyqt-applications-qthreadpool/
Код будет работать, но GUI по-прежнему зависает. Кроме того, я хотел бы иметь возможность прервать процесс с помощью analyStopButton. Это правильный способ сделать это? Я не смог узнать, потому что не могу заставить GUI перестать замерзать. Также вы можете излучать из рабочего класса в QProgresbar? Это также ускользает от меня.
# -*- coding: utf-8 -*-
import pandas as pd
import matplotlib
import funcs
import time
import math
import os
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as Canvas
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
import threading
# Ensure using PyQt5 backend
matplotlib.use('QT5Agg')
# ensures that the program is normal sized
if hasattr(QtCore.Qt, 'AA_EnableHighDpiScaling'):
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
if hasattr(QtCore.Qt, 'AA_UseHighDpiPixmaps'):
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
# Button definitions.
self.analyzeStopButton.clicked.connect(self.psmfitstop)
self.analyzeStartButton.clicked.connect(self.psmfitstart)
# set up thread pool
self.threadpool = QtCore.QThreadPool()
print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
def loadfiles(self):
try:
self.delG_df = pd.DataFrame()
self.delG_df['ϕΣμ'] =[0.3075977993911359, 0.24858871842849484, 0.17810735102260153, 0.14749389736592416, 0.13030824516428058, 0.09995113131681002, 0.09498080450119177]
self.delG_df['Fluence'] =[7718000000000.0, 15400000000000.0, 38680000000000.0, 48660000000000.0, 77150000000000.0, 122300000000000.0, 154000000000000.0]
except:
print("Error in loadfiles")
def psmfitstart(self):
# when the start button is pushed we want to make it unable
# to be pushed again but we do want the stop button to be able to be pushed
self.analyzeStartButton.setEnabled(False)
self.analyzeStopButton.setEnabled(True)
self.loadfiles() # just for this to load in the data. Data will be produced from other functions later.
# self.stop tracks whether or not the button has been pushed.
global stop_thread, psmfitSteps, psmMin, psmMax, k1, k2Steps, k2min, k2max, k3Steps, k3min, k3max, thickness, FA,elements, experimental, fluence
stop_thread = False
# sets the progress bar to 0%
self.completed = 0
self.progressBar.setValue(self.completed)
# get all the values from groupbox 2. There are more but I deleted them to make this shorter.
psmfitSteps=int(self.psmfitstepslineedit.text())
psmMin=eval(self.psmminlineedit.text())
# These will be used in the run function.
experimental = self.delG_df['∆G'].tolist()
fluence = self.delG_df['Fluence'].tolist()
elements = len(fluence)
# activate worker function (Still freezes up)
self.worker = Worker(psmfitSteps, psmMin, psmMax, k1, k2Steps, k2min, k2max, k3Steps, k3min, k3max, thickness, FA, elements, experimental, fluence) # Any other args, kwargs are passed to the run function
self.threadpool.start(self.worker)
self.event_stop = threading.Event()
# creates pandas dataframe from lists.
self.df_fit = pd.DataFrame()
self.df_fit['fit_fluence'] = fittedSeriesFluence
self.df_fit['fit_pSm'] = fittedSeriesElements
# tell the progress bar that we are finished with our calculations.
self.completed = 100
self.progressBar.setValue(self.completed)
# if we complete the process make it to where we can push to fit again
# and run the program with a new set of parameters.
if self.completed == 100:
self.analyzeStartButton.setEnabled(True)
self.analyzeStopButton.setEnabled(False)
def psmfitstop(self):
self.event_stop.set() # maybe it works I won't know until I can push it.
self.analyzeStartButton.setEnabled(True)
self.analyzeStopButton.setEnabled(False)
print("stop fitting the data")
class Worker(QRunnable):
'''
Worker thread
Inherits from QRunnable to handler worker thread setup, signals and wrap-up.
'''
def __init__(self, psmfitSteps, psmMin, psmMax, k1, k2Steps, k2min, k2max, k3Steps, k3min, k3max, thickness, FA, elements, experimental, fluence):
super(Worker, self).__init__()
self.run(psmfitSteps, psmMin, psmMax, k1, k2Steps, k2min, k2max, k3Steps, k3min, k3max, thickness, FA, elements, experimental, fluence)
@pyqtSlot()
def run(self, psmfitSteps, psmMin, psmMax, k1, k2Steps, k2min, k2max, k3Steps, k3min, k3max, thickness, FA, elements, experimental, fluence):
global fitted, optimalpSm, optimalk2, optimalk3, fittedSeriesElements, fittedSeriesFluence
def R(I0in, k1in, k2in, k3in):
return nOut[nOutMaxIndex] / nPrimeOut[nOutMaxIndex]
def run_fit():
# long function
R(I0in, k1in, k2in, k3in)
run_fit()
class MplCanvas(Canvas): # Matplotlib canvas class to create figure
def __init__(self):
self.fig = Figure()
self.ax = self.fig.add_subplot(111)
Canvas.__init__(self, self.fig)
Canvas.updateGeometry(self)
class MplWidget(QtWidgets.QWidget): # Matplotlib widget
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent) # Inherit from QWidget
self.canvas = MplCanvas() # Create canvas object
self.vbl = QtWidgets.QVBoxLayout() # Set box for plotting
self.vbl.addWidget(self.canvas)
self.setLayout(self.vbl)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())