[PyQt] Signals across threads

Gwendolyn van der Linden G.W.vanderLinden at rijnhuizen.nl
Wed Aug 8 15:15:27 BST 2007


Hi,

I'm using PyQt4, version 4.2.3, on Windows XP.  It seems that signals
emit()'ed from the GUI thread are delivered to other threads in the GUI
thread, rather than in the target thread.  The following program
demonstrates this:

-------------------------

import sys
from PyQt4 import QtGui, QtCore

class WorkerThread(QtCore.QThread):
    def __init__(self):
        QtCore.QThread.__init__(self)
    def slotDo(self):
        print 'slotDo called in thread:', self.currentThread()
        self.emit(QtCore.SIGNAL('done'))
    def run(self):
        print 'Worker thread:', self.currentThread()
        self.exec_()

class MainWindow(QtGui.QMainWindow):
    def __init__(self):
        self.i = 1
        QtGui.QMainWindow.__init__(self)
        self.widget = QtGui.QPushButton('Do %i' % self.i)
        self.connect(self.widget, QtCore.SIGNAL('clicked()'),
self.slotClicked)
        self.setCentralWidget(self.widget)
    def slotClicked(self):
        self.emit(QtCore.SIGNAL('do'))
    def slotDone(self):
        self.i += 1
        self.widget.setText('Do %i' % self.i)

def main(args):
    app = QtGui.QApplication(sys.argv)
    win = MainWindow()
    win.show()
    worker = WorkerThread()
    worker.start()
    app.connect(win, QtCore.SIGNAL('do'), worker.slotDo)
    app.connect(worker, QtCore.SIGNAL('done'), win.slotDone)
    print 'Main thread:', app.instance().thread()
    app.exec_()

if __name__ == "__main__":
    main(sys.argv)

-------------------------

This gives (after clicking the button once):

  Main thread: <PyQt4.QtCore.QThread object at 0x009E78E8>
  Worker thread: <__main__.WorkerThread object at 0x009E78A0>
  slotDo called in thread: <PyQt4.QtCore.QThread object at 0x009E78E8>

As you can see, the 'slotDo' method from the worker thread is called
from the GUI thread.  This behaviour means that time consuming code in
the worker thread slots will block the GUI.  I was under the impression
that the signal/slot mechanism is supposed to see that 'win' and
'worker' are in two different threads, and that the event loop in the
worker thread will catch the emit()'ed signal.

Is this a bug, or am I missing something here?

Thanks,
Gwendolyn.




More information about the PyQt mailing list