I have this code:
from PySide import QtCore, QtGui
import time
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 133)
self.progressBar = QtGui.QProgressBar(Dialog)
self.progressBar.setGeometry(QtCore.QRect(20, 10, 361, 23))
self.progressBar.setProperty("value", 24)
self.progressBar.setObjectName("progressBar")
self.pushButton = QtGui.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(20, 40, 361, 61))
self.pushButton.setObjectName("pushButton")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.setText(QtGui.QApplication.translate("Dialog", "PushButton", None, QtGui.QApplication.UnicodeUTF8))
self.progressBar.setValue(0)
self.pushButton.clicked.connect(self.progress)
def progress(self):
self.progressBar.minimum = 1
self.progressBar.maximum = 100
for i in range(1, 101):
self.progressBar.setValue(i)
time.sleep(0.1)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
Dialog = QtGui.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
I want to have the progress bar in a separate thread, so it doesn't freeze up the application, but I can't seem to find how to do so.
Can anyone please help?
I think you may be mistaken. You want the work you're doing in a separate thread so it doesn't freeze the application. But you also want to be able to update the progress bar. You can achieve this by creating a worker class using a QThread
. QThreads are able emit signals, which your UI can listen for and act appropriately.
First, let's create your worker class.
#Inherit from QThread
class Worker(QtCore.QThread):
#This is the signal that will be emitted during the processing.
#By including int as an argument, it lets the signal know to expect
#an integer argument when emitting.
updateProgress = QtCore.Signal(int)
#You can do any extra things in this init you need, but for this example
#nothing else needs to be done expect call the super's init
def __init__(self):
QtCore.QThread.__init__(self)
#A QThread is run by calling it's start() function, which calls this run()
#function in it's own "thread".
def run(self):
#Notice this is the same thing you were doing in your progress() function
for i in range(1, 101):
#Emit the signal so it can be received on the UI side.
self.updateProgress.emit(i)
time.sleep(0.1)
So now that you have a worker class, it's time to make use of it. You will want to create a new function in your Ui_Dialog
class to handle the emitted signals.
def setProgress(self, progress):
self.progressBar.setValue(progress)
While you're there, you can remove your progress()
function.
in retranslateUi()
you will want to update the push button event handler from
self.pushButton.clicked.connect(self.progress)
to
self.pushButton.clicked.connect(self.worker.start)
Finally, in your setupUI()
function, you will need to create an instance of your worker class and connect it's signal to your setProgress()
function.
Before this:
self.retranslateUi(Dialog)
Add this:
self.worker = Worker()
self.worker.updateProgress.connect(self.setProgress)
Here is the final code:
from PySide import QtCore, QtGui
import time
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 133)
self.progressBar = QtGui.QProgressBar(Dialog)
self.progressBar.setGeometry(QtCore.QRect(20, 10, 361, 23))
self.progressBar.setProperty("value", 24)
self.progressBar.setObjectName("progressBar")
self.pushButton = QtGui.QPushButton(Dialog)
self.pushButton.setGeometry(QtCore.QRect(20, 40, 361, 61))
self.pushButton.setObjectName("pushButton")
self.worker = Worker()
self.worker.updateProgress.connect(self.setProgress)
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
self.progressBar.minimum = 1
self.progressBar.maximum = 100
def retranslateUi(self, Dialog):
Dialog.setWindowTitle(QtGui.QApplication.translate("Dialog", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.pushButton.setText(QtGui.QApplication.translate("Dialog", "PushButton", None, QtGui.QApplication.UnicodeUTF8))
self.progressBar.setValue(0)
self.pushButton.clicked.connect(self.worker.start)
def setProgress(self, progress):
self.progressBar.setValue(progress)
#Inherit from QThread
class Worker(QtCore.QThread):
#This is the signal that will be emitted during the processing.
#By including int as an argument, it lets the signal know to expect
#an integer argument when emitting.
updateProgress = QtCore.Signal(int)
#You can do any extra things in this init you need, but for this example
#nothing else needs to be done expect call the super's init
def __init__(self):
QtCore.QThread.__init__(self)
#A QThread is run by calling it's start() function, which calls this run()
#function in it's own "thread".
def run(self):
#Notice this is the same thing you were doing in your progress() function
for i in range(1, 101):
#Emit the signal so it can be received on the UI side.
self.updateProgress.emit(i)
time.sleep(0.1)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
Dialog = QtGui.QDialog()
ui = Ui_Dialog()
ui.setupUi(Dialog)
Dialog.show()
sys.exit(app.exec_())
QThreads have some built in signals that are automatically emitted. You can see them, and more information about QThreads in the documentation