I'm trying to implement threading in a PyQT GUI but having trouble. Some background, I have a standalone script that uninstalled some software, deleted some folders, and then reinstalled a newer build. I used the threading module to delete the folders, spinning up a new thread for each. A couple of the folders were large and took some time, so I would iterate over the separate threads but skip the larger folders and join the threads:
thread = threading.Thread(name=portalDirToDelete,target=deleteFolder,args=(portalDirToDelete,))
thread.start()
....
for thread in threading.enumerate():
if not "MainThread" in thread.getName() and not "content" in thread.getName() and not "temp" in thread.getName():
thread.join()
Once I started making a UI using PyQT4, I found that the threads wouldn't start until I tried to join them. I did some reading and learned that using the threading module wouldn't work anymore, (How to keep track of thread progress in Python without freezing the PyQt GUI?) so I started to look into QThreads but haven't had much luck. Below is a simplified version of what my other script is doing:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'Samples\ThreadUI1.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
import shutil, os, time
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class workerThread(QtCore.QObject):
finished = QtCore.pyqtSignal()
def deleteFolder(self,path):
if os.path.exists(path):
shutil.rmtree(path)
self.finished.emit()
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form"))
Form.resize(115, 66)
self.runApp = QtGui.QPushButton(Form)
self.runApp.setGeometry(QtCore.QRect(20, 20, 75, 23))
self.runApp.setObjectName(_fromUtf8("runApp1"))
self.retranslateUi(Form)
QtCore.QMetaObject.connectSlotsByName(Form)
self.runApp.clicked.connect(lambda:self.runSetups())
def retranslateUi(self, Form):
Form.setWindowTitle(_translate("Form", "Form", None))
self.runApp.setText(_translate("Form", "Run App", None))
def usingMoveToThread(self,path):
self.app = QtCore.QCoreApplication([])
self.objThread = QtCore.QThread()
self.obj = workerThread()
self.obj.moveToThread(self.objThread)
self.obj.finished.connect(self.objThread.quit)
self.objThread.started.connect(self.obj.deleteFolder(path))
self.objThread.finished.connect(app.exit)
self.objThread.start()
def runSetups(self):
self.usingMoveToThread(r"C:\arcgisportal")
for x in range(1,11):
print(x)
time.sleep(1)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
Form = QtGui.QWidget()
ui = Ui_Form()
ui.setupUi(Form)
Form.show()
sys.exit(app.exec_())
I may be wrong in thinking this, but my approach was to kick off the process to delete the folders in a new thread, and see if it then continues on to print in the loop. I've been using Threading and PyQT as a main guide. There seems to be differing opinions regarding subclassing QThread or not, so I just went with this blog, (https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/) in not doing it.
I'm using Python 2.7, PyQt4 4.11.4 and this app was made through UI Designer. I know it's not a good idea to update the generated ui/py file, which I'm not doing elsewhere, just made this sample to provide as context.
Any help is appreciated!
Update
If I open a modal QMessageBox() and add a button that closes the QMessageBox, while it's open, the folders within the larger folder are deleted. Once I close the QMessageBox(), the folders stop getting deleted, so there's something that's not clear to me regarding threads and the UI.