2010-12-01 74 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_())