from PyQt4.QtCore import *
#from datetime import datetime
from PyQt4.QtGui import *
class ThreadManagerDialog(QDialog):
def __init__( self, iface, title="Worker Thread"):
QDialog.__init__( self, iface.mainWindow() )
self.iface = iface
self.setWindowTitle(title)
self.setLayout(QVBoxLayout())
self.primaryLabel = QLabel(self)
self.layout().addWidget(self.primaryLabel)
self.primaryBar = QProgressBar(self)
self.layout().addWidget(self.primaryBar)
self.secondaryLabel = QLabel(self)
self.layout().addWidget(self.secondaryLabel)
self.secondaryBar = QProgressBar(self)
self.layout().addWidget(self.secondaryBar)
self.closeButton = QPushButton("Close")
self.closeButton.setEnabled(False)
self.layout().addWidget(self.closeButton)
self.closeButton.clicked.connect(self.reject)
def run(self):
self.runThread()
self.exec_()
def runThread( self):
QObject.connect( self.workerThread, SIGNAL( "jobFinished( PyQt_PyObject )" ), self.jobFinishedFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryValue( PyQt_PyObject )" ), self.primaryValueFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryRange( PyQt_PyObject )" ), self.primaryRangeFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryText( PyQt_PyObject )" ), self.primaryTextFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryValue( PyQt_PyObject )" ), self.secondaryValueFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryRange( PyQt_PyObject )" ), self.secondaryRangeFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryText( PyQt_PyObject )" ), self.secondaryTextFromThread )
self.workerThread.start()
def cancelThread( self ):
self.workerThread.stop()
def jobFinishedFromThread( self, success ):
self.workerThread.stop()
self.primaryBar.setValue(self.primaryBar.maximum())
self.secondaryBar.setValue(self.secondaryBar.maximum())
self.emit( SIGNAL( "jobFinished( PyQt_PyObject )" ), success )
self.closeButton.setEnabled( True )
def primaryValueFromThread( self, value ):
self.primaryBar.setValue(value)
def primaryRangeFromThread( self, range_vals ):
self.primaryBar.setRange( range_vals[ 0 ], range_vals[ 1 ] )
def primaryTextFromThread( self, value ):
self.primaryLabel.setText(value)
def secondaryValueFromThread( self, value ):
self.secondaryBar.setValue(value)
def secondaryRangeFromThread( self, range_vals ):
self.secondaryBar.setRange( range_vals[ 0 ], range_vals[ 1 ] )
def secondaryTextFromThread( self, value ):
self.secondaryLabel.setText(value)
class WorkerThread( QThread ):
def __init__( self, parentThread):
QThread.__init__( self, parentThread )
def run( self ):
self.running = True
success = self.doWork()
self.emit( SIGNAL( "jobFinished( PyQt_PyObject )" ), success )
def stop( self ):
self.running = False
pass
def doWork( self ):
return True
def cleanUp( self):
pass
class CounterThread(WorkerThread):
def __init__(self, parentThread):
WorkerThread.__init__(self, parentThread)
def doWork(self):
target = 100000000
stepP= target/100
stepS=target/10000
self.emit( SIGNAL( "primaryText( PyQt_PyObject )" ), "Primary" )
self.emit( SIGNAL( "secondaryText( PyQt_PyObject )" ), "Secondary" )
self.emit( SIGNAL( "primaryRange( PyQt_PyObject )" ), ( 0, 100 ) )
self.emit( SIGNAL( "secondaryRange( PyQt_PyObject )" ), ( 0, 100 ) )
count = 0
while count < target:
if count % stepP == 0:
self.emit( SIGNAL( "primaryValue( PyQt_PyObject )" ), int(count / stepP) )
if count % stepS == 0:
self.emit( SIGNAL( "secondaryValue( PyQt_PyObject )" ), count % stepP / stepS )
if not self.running:
return False
count += 1
return True
d = ThreadManagerDialog(qgis.utils.iface, "CounterThread Demo")
d.workerThread = CounterThread(qgis.utils.iface.mainWindow())
d.run()
from PyQt4.QtCore import *
#from datetime import datetime
from PyQt4.QtGui import *
class ThreadManagerDialog(QDialog):
def __init__( self, iface, title="Worker Thread"):
QDialog.__init__( self, iface.mainWindow() )
self.iface = iface
self.setWindowTitle(title)
self.setLayout(QVBoxLayout())
self.primaryLabel = QLabel(self)
self.layout().addWidget(self.primaryLabel)
self.primaryBar = QProgressBar(self)
self.layout().addWidget(self.primaryBar)
self.secondaryLabel = QLabel(self)
self.layout().addWidget(self.secondaryLabel)
self.secondaryBar = QProgressBar(self)
self.layout().addWidget(self.secondaryBar)
self.closeButton = QPushButton("Close")
self.closeButton.setEnabled(False)
self.layout().addWidget(self.closeButton)
self.closeButton.clicked.connect(self.reject)
def run(self):
self.runThread()
self.exec_()
def runThread( self):
QObject.connect( self.workerThread, SIGNAL( "jobFinished( PyQt_PyObject )" ), self.jobFinishedFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryValue( PyQt_PyObject )" ), self.primaryValueFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryRange( PyQt_PyObject )" ), self.primaryRangeFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryText( PyQt_PyObject )" ), self.primaryTextFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryValue( PyQt_PyObject )" ), self.secondaryValueFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryRange( PyQt_PyObject )" ), self.secondaryRangeFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryText( PyQt_PyObject )" ), self.secondaryTextFromThread )
self.workerThread.start()
def cancelThread( self ):
self.workerThread.stop()
def jobFinishedFromThread( self, success ):
self.workerThread.stop()
self.primaryBar.setValue(self.primaryBar.maximum())
self.secondaryBar.setValue(self.secondaryBar.maximum())
self.emit( SIGNAL( "jobFinished( PyQt_PyObject )" ), success )
self.closeButton.setEnabled( True )
def primaryValueFromThread( self, value ):
self.primaryBar.setValue(value)
def primaryRangeFromThread( self, range_vals ):
self.primaryBar.setRange( range_vals[ 0 ], range_vals[ 1 ] )
def primaryTextFromThread( self, value ):
self.primaryLabel.setText(value)
def secondaryValueFromThread( self, value ):
self.secondaryBar.setValue(value)
def secondaryRangeFromThread( self, range_vals ):
self.secondaryBar.setRange( range_vals[ 0 ], range_vals[ 1 ] )
def secondaryTextFromThread( self, value ):
self.secondaryLabel.setText(value)
class WorkerThread( QThread ):
def __init__( self, parentThread):
QThread.__init__( self, parentThread )
def run( self ):
self.running = True
success = self.doWork()
self.emit( SIGNAL( "jobFinished( PyQt_PyObject )" ), success )
def stop( self ):
self.running = False
pass
def doWork( self ):
return True
def cleanUp( self):
pass
class CounterThread(WorkerThread):
def __init__(self, parentThread):
WorkerThread.__init__(self, parentThread)
def doWork(self):
target = 100000000
stepP= target/100
stepS=target/10000
self.emit( SIGNAL( "primaryText( PyQt_PyObject )" ), "Primary" )
self.emit( SIGNAL( "secondaryText( PyQt_PyObject )" ), "Secondary" )
self.emit( SIGNAL( "primaryRange( PyQt_PyObject )" ), ( 0, 100 ) )
self.emit( SIGNAL( "secondaryRange( PyQt_PyObject )" ), ( 0, 100 ) )
count = 0
while count < target:
if count % stepP == 0:
self.emit( SIGNAL( "primaryValue( PyQt_PyObject )" ), int(count / stepP) )
if count % stepS == 0:
self.emit( SIGNAL( "secondaryValue( PyQt_PyObject )" ), count % stepP / stepS )
if not self.running:
return False
count += 1
return True
d = ThreadManagerDialog(qgis.utils.iface, "CounterThread Demo")
d.workerThread = CounterThread(qgis.utils.iface.mainWindow())
d.run()
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class ThreadManagerDialog(QDialog):
def __init__( self, iface, title="Worker Thread"):
QDialog.__init__( self, iface.mainWindow() )
self.iface = iface
self.setWindowTitle(title)
self.setLayout(QVBoxLayout())
self.primaryLabel = QLabel(self)
self.layout().addWidget(self.primaryLabel)
self.primaryBar = QProgressBar(self)
self.layout().addWidget(self.primaryBar)
self.secondaryLabel = QLabel(self)
self.layout().addWidget(self.secondaryLabel)
self.secondaryBar = QProgressBar(self)
self.layout().addWidget(self.secondaryBar)
self.closeButton = QPushButton("Close")
self.closeButton.setEnabled(False)
self.layout().addWidget(self.closeButton)
self.closeButton.clicked.connect(self.reject)
def run(self):
self.runThread()
self.exec_()
def runThread( self):
QObject.connect( self.workerThread, SIGNAL( "jobFinished( PyQt_PyObject )" ), self.jobFinishedFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryValue( PyQt_PyObject )" ), self.primaryValueFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryRange( PyQt_PyObject )" ), self.primaryRangeFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryText( PyQt_PyObject )" ), self.primaryTextFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryValue( PyQt_PyObject )" ), self.secondaryValueFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryRange( PyQt_PyObject )" ), self.secondaryRangeFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryText( PyQt_PyObject )" ), self.secondaryTextFromThread )
self.workerThread.start()
def cancelThread( self ):
self.workerThread.stop()
def jobFinishedFromThread( self, success ):
self.workerThread.stop()
self.primaryBar.setValue(self.primaryBar.maximum())
self.secondaryBar.setValue(self.secondaryBar.maximum())
self.emit( SIGNAL( "jobFinished( PyQt_PyObject )" ), success )
self.closeButton.setEnabled( True )
def primaryValueFromThread( self, value ):
self.primaryBar.setValue(value)
def primaryRangeFromThread( self, range_vals ):
self.primaryBar.setRange( range_vals[ 0 ], range_vals[ 1 ] )
def primaryTextFromThread( self, value ):
self.primaryLabel.setText(value)
def secondaryValueFromThread( self, value ):
self.secondaryBar.setValue(value)
def secondaryRangeFromThread( self, range_vals ):
self.secondaryBar.setRange( range_vals[ 0 ], range_vals[ 1 ] )
def secondaryTextFromThread( self, value ):
self.secondaryLabel.setText(value)
class WorkerThread( QThread ):
def __init__( self, parentThread):
QThread.__init__( self, parentThread )
def run( self ):
self.running = True
success = self.doWork()
self.emit( SIGNAL( "jobFinished( PyQt_PyObject )" ), success )
def stop( self ):
self.running = False
pass
def doWork( self ):
return True
def cleanUp( self):
pass
class CounterThread(WorkerThread):
def __init__(self, parentThread):
WorkerThread.__init__(self, parentThread)
def doWork(self):
target = 100000000
stepP= target/100
stepS=target/10000
self.emit( SIGNAL( "primaryText( PyQt_PyObject )" ), "Primary" )
self.emit( SIGNAL( "secondaryText( PyQt_PyObject )" ), "Secondary" )
self.emit( SIGNAL( "primaryRange( PyQt_PyObject )" ), ( 0, 100 ) )
self.emit( SIGNAL( "secondaryRange( PyQt_PyObject )" ), ( 0, 100 ) )
count = 0
while count < target:
if count % stepP == 0:
self.emit( SIGNAL( "primaryValue( PyQt_PyObject )" ), int(count / stepP) )
if count % stepS == 0:
self.emit( SIGNAL( "secondaryValue( PyQt_PyObject )" ), count % stepP / stepS )
if not self.running:
return False
count += 1
return True
d = ThreadManagerDialog(qgis.utils.iface, "CounterThread Demo")
d.workerThread = CounterThread(qgis.utils.iface.mainWindow())
d.run()
So I had another look at this problem. I started from scratch and had success, then went back to look at the code above and still can't fix it.
In the interests of providing a working example for anyone researching this subject I will provide functional code here:
from PyQt4.QtCore import *
#from datetime import datetime
from PyQt4.QtGui import *
class ThreadManagerDialog(QDialog):
def __init__( self, iface, title="Worker Thread"):
QDialog.__init__( self, iface.mainWindow() )
self.iface = iface
self.setWindowTitle(title)
self.setLayout(QVBoxLayout())
self.primaryLabel = QLabel(self)
self.layout().addWidget(self.primaryLabel)
self.primaryBar = QProgressBar(self)
self.layout().addWidget(self.primaryBar)
self.secondaryLabel = QLabel(self)
self.layout().addWidget(self.secondaryLabel)
self.secondaryBar = QProgressBar(self)
self.layout().addWidget(self.secondaryBar)
self.closeButton = QPushButton("Close")
self.closeButton.setEnabled(False)
self.layout().addWidget(self.closeButton)
self.closeButton.clicked.connect(self.reject)
def run(self):
self.runThread()
self.exec_()
def runThread( self):
QObject.connect( self.workerThread, SIGNAL( "jobFinished( PyQt_PyObject )" ), self.jobFinishedFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryValue( PyQt_PyObject )" ), self.primaryValueFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryRange( PyQt_PyObject )" ), self.primaryRangeFromThread )
QObject.connect( self.workerThread, SIGNAL( "primaryText( PyQt_PyObject )" ), self.primaryTextFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryValue( PyQt_PyObject )" ), self.secondaryValueFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryRange( PyQt_PyObject )" ), self.secondaryRangeFromThread )
QObject.connect( self.workerThread, SIGNAL( "secondaryText( PyQt_PyObject )" ), self.secondaryTextFromThread )
self.workerThread.start()
def cancelThread( self ):
self.workerThread.stop()
def jobFinishedFromThread( self, success ):
self.workerThread.stop()
self.primaryBar.setValue(self.primaryBar.maximum())
self.secondaryBar.setValue(self.secondaryBar.maximum())
self.emit( SIGNAL( "jobFinished( PyQt_PyObject )" ), success )
self.closeButton.setEnabled( True )
def primaryValueFromThread( self, value ):
self.primaryBar.setValue(value)
def primaryRangeFromThread( self, range_vals ):
self.primaryBar.setRange( range_vals[ 0 ], range_vals[ 1 ] )
def primaryTextFromThread( self, value ):
self.primaryLabel.setText(value)
def secondaryValueFromThread( self, value ):
self.secondaryBar.setValue(value)
def secondaryRangeFromThread( self, range_vals ):
self.secondaryBar.setRange( range_vals[ 0 ], range_vals[ 1 ] )
def secondaryTextFromThread( self, value ):
self.secondaryLabel.setText(value)
class WorkerThread( QThread ):
def __init__( self, parentThread):
QThread.__init__( self, parentThread )
def run( self ):
self.running = True
success = self.doWork()
self.emit( SIGNAL( "jobFinished( PyQt_PyObject )" ), success )
def stop( self ):
self.running = False
pass
def doWork( self ):
return True
def cleanUp( self):
pass
class CounterThread(WorkerThread):
def __init__(self, parentThread):
WorkerThread.__init__(self, parentThread)
def doWork(self):
target = 100000000
stepP= target/100
stepS=target/10000
self.emit( SIGNAL( "primaryText( PyQt_PyObject )" ), "Primary" )
self.emit( SIGNAL( "secondaryText( PyQt_PyObject )" ), "Secondary" )
self.emit( SIGNAL( "primaryRange( PyQt_PyObject )" ), ( 0, 100 ) )
self.emit( SIGNAL( "secondaryRange( PyQt_PyObject )" ), ( 0, 100 ) )
count = 0
while count < target:
if count % stepP == 0:
self.emit( SIGNAL( "primaryValue( PyQt_PyObject )" ), int(count / stepP) )
if count % stepS == 0:
self.emit( SIGNAL( "secondaryValue( PyQt_PyObject )" ), count % stepP / stepS )
if not self.running:
return False
count += 1
return True
d = ThreadManagerDialog(qgis.utils.iface, "CounterThread Demo")
d.workerThread = CounterThread(qgis.utils.iface.mainWindow())
d.run()
The structure of this sample is a ThreadManagerDialog class that than can be assigned a WorkerThread (or subclass). When the dialog's run method is called it will in turn call the doWork method on the worker. The result is that any code in doWork will run in a seperate thread, leaving the GUI free to respond to user input.
In this sample an instance of CounterThread is assigned as the worker and a couple of progress bars will be kept busy for a minute or so.
Note: this is formatted so that it is ready to paste into the python console. The last three lines will need to be removed before saving to a .py file.