【问题标题】:Add a progress Bar to a method in PyQt5在 PyQt5 中为方法添加进度条
【发布时间】:2019-04-21 03:02:37
【问题描述】:

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

下面是我的代码:

我正在从 Qtdesigner 加载用户界面。我也可以在可以附加到 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_())  

【问题讨论】:

    标签: python pyqt pyqt5 qprogressbar


    【解决方案1】:

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

    回到问题,当你运行 pdf2excel 时,你会看到你不能改变窗口的大小,因为 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_())
    

    【讨论】:

    • 谢谢你的回答!我无法提供 pdf,因为它包含一些机密信息。当我按下 pushButton_3 时,我也从上面的代码中得到这个错误! TypeError: QTimer(parent: QObject = None): argument 1 has unexpected type 'int'
    • @KartikeyaSharma 我已经更正了它,因为我无法测试它,因为所需的 pdf 非常特殊。再试一次。
    • 感谢进度条现在可以工作,但变量 self.converted_file 始终设置为无。它不会更改为在我的代码中获得的数据框/请帮助
    猜你喜欢
    • 1970-01-01
    • 2011-05-18
    • 2019-12-05
    • 2023-03-02
    • 1970-01-01
    • 1970-01-01
    • 2013-07-29
    • 1970-01-01
    相关资源
    最近更新 更多