自定义信号和多线程

Custom signals and multithreading

我一直在努力使这段代码工作,但我仍然看不出缺陷在哪里。 我正在尝试从新线程发出信号,因此主线程接收信号并执行函数。

如果我尝试在同一个线程中执行此操作,一切正常 - 但使用此代码,线程已创建,但信号从未连接。

from PyQt4.QtCore import * 
from PyQt4.QtGui import *
from PyQt4 import QtCore

class WorkThread(QtCore.QThread):
    def __init__(self):
        QtCore.QThread.__init__(self)

    def run(self):
        print("From thread")
        self.emit(QtCore.SIGNAL("trying"))
        return

class Foo(QObject):            
    def handle_trigger(self):
        print ("trigger signal received")

    def new_thread(self):
        self.get_thread = WorkThread()
        self.connect(self.get_thread, QtCore.SIGNAL("trying"), self.handle_trigger)
        self.get_thread.start()


a = Foo()
a.new_thread()

我自己糊里糊涂地解决了这个问题,我认为这对你有用。

from PyQt4.QtCore import * 
from PyQt4.QtGui import *
from PyQt4 import QtCore

class WorkThread(QtCore.QThread):
 def __init__(self):
  QtCore.QThread.__init__(self)

 tryThis =    QtCore.Signal(str)   #added this variable

 def run(self):
  print("From thread")
  x = "trying"
  self.tryThis.emit(QtCore.SIGNAL(x))  #pass your new variable like this
  return

class Foo(QObject):

    def handle_trigger(self):
        print ("trigger signal received")

    def new_thread(self):
        self.get_thread = WorkThread()        
        self.get_thread.start()
        self.get_thread.tryThis.connect(self.handle_trigger,QtCore.Qt.QueuedConnection)  #passed it here

a = Foo()
a.new_thread()

根据评论进行了编辑。

您的代码存在一个主要问题。您实际上并没有启动 Qt 应用程序,因此没有主事件循环 运行。您必须添加以下行:

app = QApplication(sys.argv)
app.exec_()

此外,您应该使用 new-style Qt signals/slots if possible, or if you stick with the old-style, know that the Qt Signal should be in the form of a C function if you want it to also work with PySide。要将其更改为与 PySide 一起使用,它将是 QtCore.SIGNAL("trying()"),而不是 QtCore.SIGNAL("trying")。有关详细信息,请参阅评论(特别是我的评论和@ekhumoro 的评论)。

这是您的代码的工作版本(使用旧式 signals/slots),我尝试尽可能少地更改,以便您可以看到微小的更改。我不得不改用 PySide,但它也应该适用于 PyQt:

from PySide.QtCore import * 
from PySide.QtGui import *
from PySide import QtCore
import sys

class WorkThread(QtCore.QThread):
    def __init__(self):
        QtCore.QThread.__init__(self)

    def run(self):
        print("From thread")
        self.emit(QtCore.SIGNAL("trying()"))

class Foo(QObject):
    def handle_trigger(self):
        print ("trigger signal received")
        self.get_thread.quit()
        self.get_thread.wait()
        QApplication.quit()

    def new_thread(self):
        self.get_thread = WorkThread()
        self.connect(self.get_thread, QtCore.SIGNAL("trying()"), self.handle_trigger)
        self.get_thread.start()

a = Foo()
a.new_thread()

app = QApplication(sys.argv)
app.exec_()

这是一个使用新 signal/slot 样式的版本(请参阅@three_pineapples 评论)。这是在 PyQt/PySide.

中实现 signals/slots 的推荐方法
from PySide.QtCore import * 
from PySide.QtGui import *
from PySide import QtCore
import sys

class WorkThread(QtCore.QThread):
    ranThread = QtCore.Signal()
    # for PyQt, use QtCore.pyqtSignal() instead

    def __init__(self):
        QtCore.QThread.__init__(self)

    def run(self):
        print("From thread")
        self.ranThread.emit()

class Foo(QObject):
    def handle_trigger(self):
        print ("trigger signal received")
        self.get_thread.quit()
        self.get_thread.wait()
        QApplication.quit()

    def new_thread(self):
        self.get_thread = WorkThread()
        self.get_thread.ranThread.connect(self.handle_trigger)
        self.get_thread.start()

a = Foo()
a.new_thread()

app = QApplication(sys.argv)
app.exec_()