简体   繁体   中英

PyQt5 Threading

Attempting to write a class that will show the progress of a threaded process. I need to use this class for all "file load" operations; however I am having trouble making it global.

fileloader.py:

from PyQt5.QtCore import pyqtSlot, pyqtSignal
from PyQt5.QtWidgets import QDialog
from PyQt5.uic import loadUi


class FileLoader(QDialog):
    completeSig = pyqtSignal()

    def __init__(self, parent=None):
        super(FileLoader, self).__init__(parent)
        self.filename = ""
        self.clientcode = ""
        self.thread = ""
        loadUi("GlobalUI/fileloader.ui", self)
        self.prgLoader.setValue(0)

    @pyqtSlot()
    def on_btnCancel_clicked(self):
        self.close()

    def closeEvent(self, e):
        self.thread.stop()

    def loadData(self):
        self.thread.totalSig.connect(self.prgLoader.setMaximum)
        self.thread.countSig.connect(self.prgLoader.setValue)
        self.thread.finished.connect(self.completed)
        self.thread.start()

    def completed(self):
        self.completeSig.emit()
        self.close()

loader.py

from PyQt5.QtCore import pyqtSignal, QThread

from fileloader import FileLoader


class DataLoader(QThread):
    totalSig = pyqtSignal(int)
    countSig = pyqtSignal(int)

    def __init__(self, parent=None):
        super(DataLoader, self).__init__(parent)
        self.threadactive = True
        self.commitsize = 300
        self.rowdata = []

    def run(self):
        print("Code Will Go Here For Loading the File")

    def stop(self):
        self.threadactive = False
        self.wait()


class PatDataLoader():
    def load(self, clientcode, filename):
        fl = FileLoader()
        fl.clientcode = clientcode
        fl.filename = filename
        fl.thread = DataLoader()
        fl.loadData()

I am calling PatDataLoader.load("test","test.txt") from another module. The problem I am running into is the application crashes with QThread: Destroyed while thread is still running as there seems to be a problem with the thread process I am passing to the fileloader. Am I not putting these pieces together properly?

main.py:

from lmdb.patloader import PatDataLoader


    class PPSReportsApp(QMainWindow):
        def __init__(self, *args):
            super(PPSReportsApp, self).__init__(*args)
            loadUi("GlobalUI/ppsreportswindow.ui", self)
            #self.showMaximized()

    @pyqtSlot()
    def on_actionTest_triggered(self):
        pl = PatDataLoader()
        pl.load("TEST","testfile.txt")

In your code pl is a local variable so it will be deleted when it finishes executing on_actionTest_triggered which is an instant possibly generating that problem. On the other hand, no load should be a static method because it does not use the self. self.thread must be None , it is better than ""

How can you prevent pl from being deleted before it is finished processing?

fl is a QDialog so you can use exec_() .

fileloader.py

class FileLoader(QDialog):
    completeSig = pyqtSignal()

    def __init__(self, parent=None):
        super(FileLoader, self).__init__(parent)
        self.filename = ""
        self.clientcode = ""
        self.thread = None
        loadUi("GlobalUI/fileloader.ui", self)
        self.prgLoader.setValue(0)

    @pyqtSlot()
    def on_btnCancel_clicked(self):
        self.close()

    def closeEvent(self, e):
        if self.thread:
            self.thread.stop()

    def loadData(self):
        if self.thread:
            self.thread.totalSig.connect(self.prgLoader.setMaximum)
            self.thread.countSig.connect(self.prgLoader.setValue)
            self.thread.finished.connect(self.completed)
            self.thread.start()

    def completed(self):
        self.completeSig.emit()
        self.close()

loader.py

class DataLoader(QThread):
    totalSig = pyqtSignal(int)
    countSig = pyqtSignal(int)

    def __init__(self, parent=None):
        super(DataLoader, self).__init__(parent)
        self.threadactive = True
        self.commitsize = 300
        self.rowdata = []

    def run(self):
        self.totalSig.emit(1000)
        print("Code Will Go Here For Loading the File")
        # emulate process
        for i in range(1000):
            if self.threadactive:
                QThread.msleep(10)
                self.countSig.emit(i)

    def stop(self):
        self.threadactive = False
        self.quit()
        self.wait()

class PatDataLoader():
    @staticmethod
    def load(clientcode, filename):
        fl = FileLoader()
        fl.clientcode = clientcode
        fl.filename = filename
        fl.thread = DataLoader()
        fl.loadData()
        fl.exec_() # <---

main.py

@pyqtSlot()
def on_actionTest_triggered(self):
    PatDataLoader.load("TEST","testfile.txt")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM