简体   繁体   English

为 PyQt5 中的方法添加进度条

[英]Add a progress Bar to a method in PyQt5

I have a simple PyQt5 app here to convert from Pdf to excel.我在这里有一个简单的 PyQt5 应用程序,可以将 Pdf 转换为 excel。 I wanted to add a progress bar to the method convert below when I click the button to convert as it takes sometime to execute,hence it will be great to have some visualization.当我点击转换按钮时,我想在下面的方法 convert 中添加一个进度条,因为它需要一些时间来执行,因此有一些可视化效果会很棒。

Here is my code below:这是我的代码如下:

I am loading the ui from the Qtdesigner.我正在从 Qtdesigner 加载 ui。 Also I can add a progress bar somewhere that can be attached to the pushButton_3 .我也可以在某处添加一个可以附加到 pushButton_3 的进度条。 Progress bar can be called 'ProgressBar' .进度条可以称为 'ProgressBar' 。 Please let me know how you can accomplish it as most of the answers here doesn't really answer this question.请让我知道您如何完成它,因为这里的大多数答案并没有真正回答这个问题。


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_())  

First of all I recommend making verifications that the variables exist or have a certain size, for example when trying to use your code with any pdf your code is broken.首先,我建议验证变量是否存在或具有特定大小,例如,当尝试将您的代码与任何 pdf 一起使用时,您的代码已损坏。

Going to the problem, when you run pdf2excel you will see that you can not change the size of the window because the GUI is frozen, so it must run on another thread and send the information as the progress and the dataframe through signals.转到问题,当您运行 pdf2excel 时,您将看到您无法更改窗口的大小,因为 GUI 已冻结,因此它必须在另一个线程上运行并通过信号将信息作为进度和数据帧发送。 In this case I will create a worker(QObject) that will live in another thread that has the pdf2excel function.在这种情况下,我将创建一个 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_())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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