在 PyQt5 的方法中添加进度条

Add a progress Bar to a method in PyQt5

我这里有一个简单的 PyQt5 应用程序可以将 Pdf 转换为 excel。当我点击转换按钮时,我想在下面的转换方法中添加一个进度条,因为它需要一些时间来执行,因此有一些可视化会很棒。

下面是我的代码:

我正在从 Qtdesigner 加载 ui。我还可以在可以附加到 pushButton_3 的某处添加一个进度条。进度条可以叫 'ProgressBar' 。请让我知道您如何完成它,因为这里的大部分答案并没有真正回答这个问题。


import sys
from PyQt5.QtWidgets import QMainWindow,QApplication,QTableView, QWidget, QFileDialog,QPushButton,QVBoxLayout,QMessageBox
from PyQt5 import uic
from PyPDF2 import PdfFileReader
from PyQt5 import QtCore,QtGui
import pandas as pd
import tabula
import re
from PandasModel import PandasModel

class App(QMainWindow):

    def __init__(self):
        QWidget.__init__(self)
        uic.loadUi('designUI.ui',self)
        self.pushButton.clicked.connect(self.openFileNameDialog)
        self.pushButton_3.clicked.connect(self.convert)
        self.pushButton_2.clicked.connect(self.view)
        self.pushButton_4.clicked.connect(self.saveFileDialog)

    def openFileNameDialog(self):    
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getOpenFileName(self,"Open File", "","All Files (*);;Python Files (*.py)")#, options=options)
        if fileName:
            self.file=fileName

    def view(self):
        model=PandasModel(self.converted_file)
        self.tableView.setModel(model)

    def convert(self):
        self.converted_file=self.pdf2excel(self.file)

    def saveFileDialog(self):    
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName, _ = QFileDialog.getSaveFileName(self, 'Save File', '', ".xls(*.xls)")
        if fileName:
            self.converted_file.to_excel(fileName)
            msg=QMessageBox()
            msg.setText('File is Saved')
            msg.setStandardButtons(QMessageBox.Ok)
            #msg.buttonClicked.connect(msgbtn) 
            msg.exec_()

    def pdf2excel(self,pdf_file):    
        pdf = PdfFileReader(open(pdf_file,'rb'))
        length=pdf.getNumPages()        
        result=pd.DataFrame(columns=['Department','Employment No','Employment Name',"Hire Date","Term Date","Birth Date",
         "Seniority Date","Pay Code","FT/PT/S","Status"])        
        page=1
        while page <= length:
            df=tabula.read_pdf(pdf_file, pages = str(page),lattice =True, area=(75.775,16.0,572.715,779.29))[1:]
            pattern = re.compile(r'(\s){2,}')
            df=pd.DataFrame(df[df.columns[0]].replace(pattern,","))
            df=df['Unnamed: 0'].str.split(",",expand=True)
            df=df.rename(columns={0:'Department',
              1:'Employment No',2:'Employment Name',3:"Hire Date",4:"Term Date",5:"Birth Date",
              6:"Seniority Date",7:"Pay Code",8:"FT/PT/S",9:"Status"})
            result=result.append(df,ignore_index=True)
            page+=1
        result["Hire Date"]=pd.to_datetime(result["Hire Date"])
        result["Term Date"]=pd.to_datetime(result["Term Date"])
        result["Days Difference"]=(result['Term Date']-result['Hire Date']).dt.days
        result=result.dropna(how='all')
        result=result.drop(columns=['Birth Date','Pay Code','Status'])
        result=result[['Department','Employment No','Employment Name',"Hire Date","Term Date","Days Difference",
         "Seniority Date","FT/PT/S"]]
        return result

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setWindowIcon(QtGui.QIcon('pdf-to-excel-icon.png'))
    ex = App()
    ex.show()
    sys.exit(app.exec_())  

首先,我建议验证变量是否存在或具有一定的大小,例如,当您尝试将您的代码与任何 pdf 一起使用时,您的代码已损坏。

问题来了,当你 运行 pdf2excel 你会看到你不能改变 window 的大小,因为 GUI 被冻结了,所以它必须 运行另一个线程并通过信号将信息作为进度和数据帧发送。在这种情况下,我将创建一个 worker(QObject),它将存在于另一个具有 pdf2excel 函数的线程中。

import sys
from functools import partial
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyPDF2 import PdfFileReader
import pandas as pd
import tabula
import re
from PandasModel import PandasModel


class PdfObject(QtCore.QObject):
    progressChanged = QtCore.pyqtSignal(int)
    maximumChanged = QtCore.pyqtSignal(int)
    pandasChanged = QtCore.pyqtSignal(pd.DataFrame)

    @QtCore.pyqtSlot(str)
    def pdf2excel(self, pdf_file):
        pdf = PdfFileReader(open(pdf_file, "rb"))
        length = pdf.getNumPages()
        result = pd.DataFrame(
            columns=[
                "Department",
                "Employment No",
                "Employment Name",
                "Hire Date",
                "Term Date",
                "Birth Date",
                "Seniority Date",
                "Pay Code",
                "FT/PT/S",
                "Status",
            ]
        )
        self.maximumChanged.emit(length)
        page = 1
        while page <= length:
            self.progressChanged.emit(page)
            df = tabula.read_pdf(
                pdf_file,
                pages=str(page),
                lattice=True,
                area=(75.775, 16.0, 572.715, 779.29),
            )[1:]
            pattern = re.compile(r"(\s){2,}")
            df = pd.DataFrame(df[df.columns[0]].replace(pattern, ","))
            df = df["Unnamed: 0"].str.split(",", expand=True)
            df = df.rename(
                columns={
                    0: "Department",
                    1: "Employment No",
                    2: "Employment Name",
                    3: "Hire Date",
                    4: "Term Date",
                    5: "Birth Date",
                    6: "Seniority Date",
                    7: "Pay Code",
                    8: "FT/PT/S",
                    9: "Status",
                }
            )
            result = result.append(df, ignore_index=True)
            page += 1
        result["Hire Date"] = pd.to_datetime(result["Hire Date"])
        result["Term Date"] = pd.to_datetime(result["Term Date"])
        result["Days Difference"] = (
            result["Term Date"] - result["Hire Date"]
        ).dt.days
        result = result.dropna(how="all")
        result = result.drop(columns=["Birth Date", "Pay Code", "Status"])
        result = result[
            [
                "Department",
                "Employment No",
                "Employment Name",
                "Hire Date",
                "Term Date",
                "Days Difference",
                "Seniority Date",
                "FT/PT/S",
            ]
        ]
        self.pandasChanged.emit(result)


class App(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(App, self).__init__(parent)
        uic.loadUi("designUI.ui", self)

        self.filename = ""
        self.converted_file = None

        thread = QtCore.QThread(self)
        thread.start()
        self.pdf_object = PdfObject()
        self.pdf_object.moveToThread(thread)
        self.pdf_object.maximumChanged.connect(self.progressBar.setMaximum)
        self.pdf_object.progressChanged.connect(self.progressBar.setValue)
        self.pdf_object.pandasChanged.connect(self.on_pandasChanged)

        self.pushButton.clicked.connect(self.openFileNameDialog)
        self.pushButton_3.clicked.connect(self.convert)
        self.pushButton_2.clicked.connect(self.view)
        self.pushButton_4.clicked.connect(self.saveFileDialog)

    def openFileNameDialog(self):
        options = QtWidgets.QFileDialog.Options()
        options |= QtWidgets.QFileDialog.DontUseNativeDialog
        fileName, _ = QtWidgets.QFileDialog.getOpenFileName(
            self, "Open File", "", "All Files (*);;Python Files (*.py)"
        )  # , options=options)
        if fileName:
            self.filename = fileName

    def view(self):
        if self.converted_file is not None:
            model = PandasModel(self.converted_file)
            self.tableView.setModel(model)

    def convert(self):
        if self.filename:
            wrapper = partial(self.pdf_object.pdf2excel, self.filename)
            QtCore.QTimer.singleShot(0, wrapper)

    @QtCore.pyqtSlot(pd.DataFrame)
    def on_pandasChanged(self, df):
        self.converted_file = df.copy()

    def saveFileDialog(self):
        options = QtWidgets.QFileDialog.Options()
        options |= QtWidgets.QFileDialog.DontUseNativeDialog
        fileName, _ = QtWidgets.QFileDialog.getSaveFileName(
            self, "Save File", "", ".xls(*.xls)"
        )
        if fileName and self.converted_file is not None:
            self.converted_file.to_excel(fileName)
            msg = QtWidgets.QMessageBox()
            msg.setText("File is Saved")
            msg.setStandardButtons(QtWidgets.QMessageBox.Ok)
            # msg.buttonClicked.connect(msgbtn)
            msg.exec_()


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    app.setWindowIcon(QtGui.QIcon("pdf-to-excel-icon.png"))
    ex = App()
    ex.show()
    sys.exit(app.exec_())