2016-01-29 89 views
2

我一直在努力使这个代码的工作,但我仍然无法看到缺陷在哪里。 我试图从一个新的线程发出信号,所以主要接收信号并执行一个函数。自定义信号和多线程

如果我尝试在同一个线程内完成它,一切正常 - 但通过此代码创建线程,但信号从未连接。

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

回答

3

根据意见编辑。

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

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

另外,如果可能的话,你应该使用new-style Qt signals/slots,或者如果你坚持使用旧的风格,知道了Qt的信号应该是,如果你是C函数的形式想要它也work with PySide。要改变这与PySide一起工作,它将是QtCore.SIGNAL("trying()"),而不是QtCore.SIGNAL("trying")。有关详细信息,请参阅评论(特别是我的和@ ekhumoro的评论)。

下面是您的代码的工作版本(使用旧式信号/插槽),我试图改变尽可能少的数量,以便您可以看到小的更改。我不得不使用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_() 

下面是使用新的信号/插槽样式(见@three_pineapples评论)版本。这是在PyQt/PySide中实现信号/插槽的推荐方式。

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

为了避免将来出现这样的错误,最好切换到新的信号和插槽类型。有关更多详细信息,请参阅[PyQt文档](http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html)。 –

+0

就@three_pineapples说的达成一致。但是说旧式信号定义必须以函数的形式出现是错误的。实际上,任何**字符串都可以用于自定义信号 - 即使是空字符串!唯一重要的是字符串匹配(虽然不*完全* - 空白被忽略)。 OPs示例中的实际错误是它不运行事件循环 - 这是处理异步,跨线程信号所需的,而不是用于同步直接信号。 – ekhumoro

+0

在我的电脑上使用PySide,省略括号会导致分段错误。 – Steve

1

我自己浑浑噩噩,我认为这会对你有用。

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