Hi Stefano,
My working example code is attached. Glad you're finding it useful.
Scott
#!/usr/bin/env python
import sys, os
from os.path import join, getsize
from PyQt4 import QtCore, QtGui
#-------------------------------------------------------------------------------
# class
#-------------------------------------------------------------------------------
class Runner(QtCore.QThread):
def __init__(self, lock, parent=None):
QtCore.QThread.__init__(self)
self.lock = lock
self.stopped = False
self.mutex = QtCore.QMutex()
self.completed = False
self.paused = False
self.rootDir = ""
def initialize(self):
self.stopped = False
self.completed = False
self.paused = False
def run(self):
print "Runner.run() ..."
self.runTask()
self.stop()
self.emit(QtCore.SIGNAL("finished(bool)"), self.completed)
def OLD_stop(self):
print "Runner.OLD_stop() ..."
try:
self.mutex.lock()
self.stopped = True
finally:
self.mutex.unlock()
def stop(self):
print "Runner.NEW_stop() ..."
with QtCore.QMutexLocker(self.mutex):
self.stopped = True
def pause(self, theBool=True):
print "Runner.pause() ..."
if theBool == False: # pause task
try:
self.mutex.lock()
self.paused = True
finally:
self.mutex.unlock()
else: # resume processing
try:
self.mutex.lock()
self.paused = False
finally:
self.mutex.unlock()
def isStopped(self):
try:
self.mutex.lock()
return self.stopped
finally:
self.mutex.unlock()
def runTask(self):
progressStr = ""
if self.isStopped():
return
# set walk dir
for root, dirs, files in os.walk(self.rootDir):
if self.isStopped():
return
while(self.paused):
QtCore.QThread.msleep(100)
try:
theSum = sum(getsize(join(root, name)) for name in files),
lenFiles = len(files)
progressStr = "%s consumes: %d bytes in %d non-directory files" % (root, theSum[0], lenFiles)
except OSError:
pass
# self.emit(QtCore.SIGNAL("setProgress(string)"), progressStr)
self.emit(QtCore.SIGNAL("setProgress(PyQt_PyObject)"), progressStr)
# completed
self.completed = True
return 0
def setRootDir(self, theDir):
self.rootDir = theDir
#-------------------------------------------------------------------------------
# class
#-------------------------------------------------------------------------------
class ConfirmDialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self)
# kill widgets
self.restartButton = QtGui.QRadioButton(self.tr("Restart task"))
self.killButton = QtGui.QRadioButton(self.tr("Kill task"))
self.killButton.setChecked(True)
self.killLayout = QtGui.QVBoxLayout()
self.killLayout.addWidget(self.restartButton)
self.killLayout.addWidget(self.killButton)
# confirm widgets
self.okButton = QtGui.QPushButton(self.tr("OK"))
self.cancelButton = QtGui.QPushButton(self.tr("Cancel"))
self.confirmLayout = QtGui.QHBoxLayout()
self.confirmLayout.addWidget(self.okButton)
self.confirmLayout.addWidget(self.cancelButton)
# dialog layout
self.formLayout = QtGui.QVBoxLayout()
self.formLayout.addLayout(self.killLayout)
self.formLayout.addLayout(self.confirmLayout)
self.setLayout(self.formLayout)
# signals/slots
# ------------------------------------------------
self.connect(self.cancelButton, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("reject()"))
self.connect(self.okButton, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("accept()"))
#-------------------------------------------------------------------------------
# class
#-------------------------------------------------------------------------------
class ThreadTest(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self)
self.rootLabel = QtGui.QLabel(self.tr("Root Dir"))
self.rootEdit = QtGui.QLineEdit()
self.rootLayout = QtGui.QHBoxLayout()
self.rootLayout.addWidget(self.rootLabel)
self.rootLayout.addWidget(self.rootEdit)
self.startButton = QtGui.QPushButton(self.tr("Start"))
self.pauseButton = QtGui.QPushButton(self.tr("Pause"))
self.pauseButton.setCheckable(True)
self.stopButton = QtGui.QPushButton(self.tr("Stop"))
self.buttonLayout = QtGui.QHBoxLayout()
self.buttonLayout.addWidget(self.startButton)
self.buttonLayout.addWidget(self.pauseButton)
self.buttonLayout.addWidget(self.stopButton)
self.formLayout = QtGui.QHBoxLayout()
self.formLayout.addLayout(self.rootLayout)
self.formLayout.addLayout(self.buttonLayout)
self.setLayout(self.formLayout)
# signals/slots
# ------------------------------------------------
self.startButton.clicked.connect(self.startTask)
self.connect(self.pauseButton, QtCore.SIGNAL("toggled(bool)"), self.pauseTask)
self.stopButton.clicked.connect(self.stopTask)
# init runner object
# ------------------------------------------------
self.lock = QtCore.QReadWriteLock()
self.runner = Runner(self.lock, self)
# self.connect(self.runner, QtCore.SIGNAL("setProgress(string)"), self.setProgress)
self.connect(self.runner, QtCore.SIGNAL("setProgress(PyQt_PyObject)"), self.setProgress)
self.connect(self.runner, QtCore.SIGNAL("finished(bool)"), self.finished)
def setProgress(self, theString):
print "setProgress: ", theString
def finished(self, theBool):
print "finished: ", theBool
def startTask(self):
self.runner.setRootDir(str(self.rootEdit.text()))
self.runner.start()
def pauseTask(self, isPaused):
if isPaused:
self.pauseButton.setText("Resume")
self.runner.pause(False) # reverse polarity of theBool
else:
self.pauseButton.setText("Pause")
self.runner.pause(True)
def stopTask(self):
# stop task
if self.runner.isRunning():
self.runner.stop()
# reset button text
self.stopButton.setText("Restart/Kill...")
if not self.runner.isRunning():
# allow restart or kill
form = ConfirmDialog()
form.setWindowTitle(self.tr("Confirm"))
if form.exec_():
if form.restartButton.isChecked():
self.runner.initialize()
self.startTask()
elif form.killButton.isChecked():
self.stopButton.setText("Stop")
if self.runner.isRunning():
self.runner.stop()
else:
pass
#-------------------------------------------------------------------------------
# main
#-------------------------------------------------------------------------------
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
form = ThreadTest()
form.setWindowTitle("Thread Test")
form.show()
sys.exit(app.exec_())
On Apr 18, 2010, at 9:54 PM, Massimo Di Stefano wrote:
Hi,
i'm tring to modify the code you pasted
using the suggested modification, but i'm not able to run it
with a "working" pause action.
Can you point me to a working version,
i'm tring to learn from it.
It is a cool example to learn how to use thread in PyQt
Thanks a lot!!!
Massimo.
Il giorno 15/apr/2010, alle ore 22.24, Russell Valentine ha scritto:
What about just put this in your for loop. Then the pause/resume
button
or whatever just toggles self.paused? That seems good to me.
while(self.paused):
QThread.msleep(100)
On 04/15/10 13:53, Scott Frankel wrote:
Hi all,
What's the best way to pause and resume processing in QThread
objects?
I've built a small test app that sets up a Python os.walk()
process that
I'd like to be able to pause and restart from where it left off.
The
documentation on QWaitCondition looks promising, though my app
appears
to hang on this line (line 69):
self.condition.wait(self.mutex)
Also, in testing for a paused job in my processing method (line
104),
does a waiting thread resume from where it left off? Or do I need
to
keep track of where it is myself and restart it from there?
Thanks in advance!
Scott
_______________________________________________
PyQt mailing list PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt
_______________________________________________
PyQt mailing list PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt
_______________________________________________
PyQt mailing list PyQt@riverbankcomputing.com
http://www.riverbankcomputing.com/mailman/listinfo/pyqt