Я пытаюсь выяснить, почему GUI все еще зависает. Я пытался реализовать рабочий класс, и я не знаю, правильно ли я это сделал - PullRequest
0 голосов
/ 23 апреля 2020

Я без особой удачи пытался заставить это работать, и я исключаю все ненужные вещи. Я основывал это на этом примере здесь. 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_())
...