I'm having some problems with communicating between Threads in PyQt. I'm using signals to communicate between two threads, a Sender and a Listener. The sender sends messages, which are expected to be received by the listener. However, no messages are receieved. Can anyone suggest what might be going wrong? I'm sure it must be something simple, but I've been looking around for hours and not found anything. Thanks in advance!
from PyQt4 import QtCore,QtGui
import time
class Listener(QtCore.QThread):
def __init__(self):
super(Listener,self).__init__()
def run(self):
# just stay alive, waiting for messages
print 'Listener started'
while True:
print '...'
time.sleep(2)
def say_hello(self):
print ' --> Receiver: Hello World!'
class Sender(QtCore.QThread):
# a signal with no arguments
signal = QtCore.pyqtSignal()
def __init__(self):
super(Sender,self).__init__()
# create and start a listener
self.listener = Listener()
self.listener.start()
# connect up the signal
self.signal.connect(self.listener.say_hello)
# start this thread
self.start()
def run(self):
print 'Sender starting'
# send five signals
for i in range(5):
print 'Sender -->'
self.signal.emit()
time.sleep(2)
# the sender's work is done
print 'Sender finished'
I'm not sure if that is what you need, but it works fine...
from PyQt4 import QtCore,QtGui
import time
class Listener(QtCore.QThread):
def __init__(self):
super(Listener,self).__init__()
def run(self):
print('listener: started')
while True:
time.sleep(2)
def connect_slots(self, sender):
self.connect(sender, QtCore.SIGNAL('testsignal'), self.say_hello)
def say_hello(self):
print('listener: received signal')
class Sender(QtCore.QThread):
def __init__(self):
super(Sender,self).__init__()
def run(self):
for i in range(5):
print('sender: sending signal')
self.emit(QtCore.SIGNAL('testsignal'))
time.sleep(2)
print('sender: finished')
if __name__ == '__main__':
o_qapplication = QtGui.QApplication([])
my_listener = Listener()
my_sender = Sender()
my_listener.connect_slots(my_sender)
my_listener.start()
my_sender.start()
i_out = o_qapplication.exec_()
The problem is that a QThread to send/receiver SIGNALS, it needs to be running an EventLoop. You aren't, so there is no opportunity to the thread to respond. Check out this blog post: You're doing it wrong
Here's an example that works for me - note the you need to call moveToThread BEFORE you connect the signals (this wasn't mentioned in the blog - not sure if it is specific to PyQt), otherwise they will run in the main thread.
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import time
class MyThread(QThread):
def __init__(self, name):
super(MyThread, self).__init__()
self.setObjectName(name)
def run(self):
print "RUN", QThread.currentThread().objectName(), QApplication.instance().thread().objectName()
self.exec_()
print "RUN DONE", QThread.currentThread().objectName()
class Producer(QObject):
def __init__(self, parent=None):
super(Producer, self).__init__(parent)
def Start(self):
for i in range(5):
print "Producer",i,QThread.currentThread().objectName()
self.emit(SIGNAL("testsignal"),i)
time.sleep(2)
time.sleep(1)
qApp.quit()
class Consumer(QObject):
def __init__(self, parent=None):
super(Consumer, self).__init__(parent)
def Consume(self, i):
print "Consumed",i,QThread.currentThread().objectName()
if __name__ == "__main__":
app = QApplication([])
producer = Producer()
consumer = Consumer()
QThread.currentThread().setObjectName("MAIN")
producerThread = MyThread("producer")
consumerThread = MyThread("consumer")
producer.moveToThread(producerThread)
consumer.moveToThread(consumerThread)
producerThread.started.connect(producer.Start)
producer.connect(producer, SIGNAL("testsignal"), consumer.Consume)
def aboutToQuit():
producerThread.quit()
consumerThread.quit()
time.sleep(1)
qApp.aboutToQuit.connect(aboutToQuit)
consumerThread.start()
time.sleep(.1)
producerThread.start()
sys.exit(app.exec_())