2010-12-01 76 views
5

我在PyQt中的线程之间进行通信时遇到了一些问题。我正在使用信号在两个线程之间进行通信,即发件人和听众。发件人发送消息,这些消息有望由收听者接收。但是,不会收到任何消息。任何人都可以提出什么可能会出错?我确信它一定是简单的,但我一直在四处寻找,没有发现任何东西。提前致谢!PyQt中的线程和信号问题

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' 
+0

Qt的决定发出一个信号,该线程取决于哪个线程创建的对象实例的信号。如果你从你的主线程创建一个监听对象并将信号发送给它的含义,它会调用它们在主线程中。请记住,该对象不是线程。见例如ftp://ftp.qt.nokia.com/videos/DevDays2007/DevDays2007%20-%20Multi-threading_in_Qt.pdf,详细了解Qt中的“线程关联”。 – 2010-12-01 14:10:18

回答

5

我不知道,如果这是你所需要的,但它工作正常...

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_() 
4

的问题是,一个QThread的发送/接收器的信号,它需要运行一个EventLoop。你不是,所以没有机会让线程回应。看看这个博客文章:You're doing it wrong

下面是一个适用于我的例子 - 注意你需要在连接信号之前调用moveToThread(这在博客中没有提及 - 不知道它是否特定于PyQt) ,否则它们将在主线程中运行。

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_())