PyQt中的线程和信号问题

6

我在使用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'

Qt根据创建对象实例的线程来决定将信号发送到哪个线程。这意味着,如果您从主线程创建一个Listener对象并向其发送信号,则它将在主线程中调用它们。请记住,对象不是线程。有关Qt中“线程亲和性”的详细信息,请参见例如ftp://ftp.qt.nokia.com/videos/DevDays2007/DevDays2007%20-%20Multi-threading_in_Qt.pdf。 - FrankH.
2个回答

5

我不确定那是否是你需要的,但它能很好地工作...


(注意:保留了原有的HTML标签)
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_()

5
问题在于,如果一个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_())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接