[PyQt] qthread and connections

Matt Smith melkor at orangepalantir.org
Fri Jan 8 02:51:59 GMT 2010


If I have a QThread how do I connect signals to it so that it receives
signals and the slot is executed in a separate thread.  

My understanding is that if I call a QThread.exec_() then I start that
thread's event loop.  A signal that is connected to the thread should be
evaluated during that threads event loop and hence it should be
evaluated in the same thread the event loop was started.   

Here is an example that creates three different buttons to show the
different ways to start a thread.  I would expect buttonB
"ConnectedThread" to behave similar to buttonA, "DirectThread", but as
can be seen it behaves like buttonC, which uses no threads.  I have
tried different connection styles but I still get the same results.


<pycode name="compare_threads.py">

#!/usr/bin/env python
from PyQt4 import QtCore,QtGui
import sys, time

class DisplayWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        widge = QtGui.QWidget()
        layout = QtGui.QVBoxLayout()
        self.ok = True
        self.label = QtGui.QLabel("0")
        button_layout = QtGui.QHBoxLayout()
        
        buttonA = QtGui.QPushButton("Direct")
        buttonB = QtGui.QPushButton("Connected")
        buttonC = QtGui.QPushButton("No Thread")
        
        buttonA.clicked.connect(self.startDirectThread)
        
        self.proc = ConnectedThread()
        self.proc.start()
        
        buttonB.clicked.connect(self.proc.stopNWait,
type=QtCore.Qt.QueuedConnection)
        
        buttonC.clicked.connect(self.sleepNoThread)
        
        
        button_layout.addWidget(buttonA)
        button_layout.addWidget(buttonB)
        button_layout.addWidget(buttonC)
        
        layout.addWidget(self.label)
        layout.addLayout(button_layout)
        widge.setLayout(layout)
        self.setCentralWidget(widge)
        
        
    @QtCore.pyqtSlot()
    def startDirectThread(self):
        if self.ok:
            self.ok = False
            self.x = DirectThread()
            self.x.start()
            self.x.finished.connect(self.xFinished)
            
    @QtCore.pyqtSlot()
    def sleepNoThread(self):
        print QtCore.QThread.currentThreadId()
        QtCore.QThread.sleep(1)
        
    @QtCore.pyqtSlot()
    def xFinished(self):
        print QtCore.QThread.currentThreadId()
        self.ok = True
        
        
class DirectThread(QtCore.QThread):
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self,parent)
    def run(self):
        print QtCore.QThread.currentThreadId()
        QtCore.QThread.sleep(1)
        
class ConnectedThread(QtCore.QThread):
    def __init__(self, parent=None):
        QtCore.QThread.__init__(self,parent)
    def run(self):
        print "Connected id: ",QtCore.QThread.currentThreadId()
        self.exec_()
    @QtCore.pyqtSlot()
    def stopNWait(self):
        print QtCore.QThread.currentThreadId()
        QtCore.QThread.sleep(1)


if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    wid = DisplayWindow()
    wid.show()
    sys.exit(app.exec_())
</pycode>



More information about the PyQt mailing list