I am building a Windows 10 GUI using PyQT5. The application allows the user to click a button, select an XML file that contains a bunch of file names, then creates a ZIP file from those names.
I have a working bare bones Python script with no GUI.
Problems arise when the PyQT5 GUI is added. I am using a QT listWidget to show the file names contained in the XML file. A button press event in the main window calls function "A" to prompt the user for the XML file and populate the QT listWidget.
If I add the code to create the ZIP file to the end function "A", everything works fine, but the QT listWidget stays blank for a long time, making it appear the program is unresponsive. (There is apparently no way to update, repaint, or refresh the QT listWidget before a function finishes.)
I would like to call function "A" to get the XML file and populate the QT listWidget, then call function "B" to create the ZIP file.
How can I execute function "B" only after function "A" has finished?
Minimum Reproducible Code is
# Python script to read HEC-RAS RasMapper (*.rasmapper) file and create a single zip file of all applicable related files and directories.import tkinter as tkfrom tkinter import filedialogimport osfrom pathlib import Pathfrom zipfile import ZipFilefrom xml.etree import ElementTree as ETimport reglobal FilesToPack, RASpath#The code below was generated by QT Designer////////////////////////from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(1000, 700) MainWindow.setMinimumSize(QtCore.QSize(1200, 700)) MainWindow.setMaximumSize(QtCore.QSize(3000, 2000)) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.formLayout = QtWidgets.QFormLayout(self.centralwidget) self.formLayout.setObjectName("formLayout") self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setMinimumSize(QtCore.QSize(200, 0)) self.pushButton.setBaseSize(QtCore.QSize(0, 0)) self.pushButton.setObjectName("pushButton") self.pushButton.setText("Begin Packing") self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.pushButton) self.listWidget = QtWidgets.QListWidget(self.centralwidget) self.listWidget.setObjectName("listWidget") self.formLayout.setWidget(5, QtWidgets.QFormLayout.SpanningRole, self.listWidget) MainWindow.setCentralWidget(self.centralwidget) QtCore.QMetaObject.connectSlotsByName(MainWindow) #The code above was generated by QT Designer//////////////////////// root = tk.Tk() root.withdraw() self.pushButton.clicked.connect(self.PackingProcess) self.PackFile() #Need this function to execute only after PackingProcess function has set FilesToPack and RASpath def PackingProcess(self): self.listWidget.clear() RASmapfile = filedialog.askopenfilename(title="Select the HEC-RAS RasMapper file to process", filetypes=[("RasMapper file","*.rasmap")]) self.listWidget.addItem(RASmapfile) RASpath = str(Path(RASmapfile).parent) # Using dummy filenames here for Minimum Reproducible Code to avoid having to post large data files FilesToPack = ["File1", "File2", "File3", "File4"] for f in FilesToPack: self.listWidget.addItem(f) def PackFile(self): #Put the files into a single ZIP file PackedZipFileName = filedialog.asksaveasfile(mode='w', title="Save the HEC-RAS RasMapper ZIP file as...", filetypes=[("ZIP file","*.zip")], defaultextension=".zip") zipObj = ZipFile(PackedZipFileName.name, mode='w') for f in FilesToPack: zipObj.write(f, f[len(RASpath):] if f.startswith(RASpath) else f) # eliminate long path prefix so files are packed in relative address form zipObj.close() def addItem(self,textitem): self.listWidget.addItem(textitem)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_())