Python PyQt:是否可以将QThread与非GUI程序一起使用?

pan*_*ish 1 python multithreading pyqt pyqt4

我有一个Python PyQt应用程序,显示一个简单的UI.当用户单击UI中的按钮时,它会触发QThread.线程的使用可防止UI在线程运行时"冻结".我发出信号以将信息从运行线程传递回UI以进行状态更新并指示完成.一切正常如上所述,我为我的UI创建了一个简单的类来调用它创建线程并运行我的通用处理.

但是,我还想创建我的程序的命令行版本(无GUI)并使用相同的处理QThread类.但是,当我尝试连接信号时,出现以下错误.QThread似乎只适用于GUI程序?

AttributeError: MyClass instance has no attribute 'connect'
Run Code Online (Sandbox Code Playgroud)

是否可以将QThread与非GUI程序一起使用?

from PyQt4 import QtCore
from PyQt4.QtCore import * 

#======================================

class MyProcess(QThread):

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

    def __del__(self):
        self.quit()
        self.wait()  

    def run(self):
        print "do time intensive process here"  
        self.emit( SIGNAL('processdone'), "emitting signal processdone") 
        return       

#====================================== 

class MyClass(QObject):

    def __init__(self, parent=None):            # All QObjects receive a parent argument (default to None)
        super(MyClass, self).__init__(parent)   # Call parent initializer.

        thread1 = MyProcess()  # uses QThread and emits signal 'processdone' 
        self.connect( thread1, SIGNAL("processdone"), self.thread1done)    
        thread1.start()  

    def thread1done(self):
        print "done"      

#======================================

if __name__ == "__main__": 

    MyClass()
Run Code Online (Sandbox Code Playgroud)

Ray*_*nda 5

问题不在于QThread,问题是你connect从一个没有它的类中调用该方法.您需要MyClass从QObject继承.

在GUI中这是有效的,因为你正在使用的任何小部件(QDialog,QMainWindow,QWidget ......)它从QObject继承(直接或间接).

MyClass继承QObject你只需要:

class MyClass(QObject):                         # Specify the class your are specializing.
    def __init__(self, parent=None):            # All QObjects receive a parent argument (default to None)
        super(MyClass, self).__init__(parent)   # Call parent initializer.

        # And countinue your code here... 
Run Code Online (Sandbox Code Playgroud)

我还建议您使用新式信号和插槽支持.

一切都有效,除了processdone信号被调用,但显然它永远不会触发对thread1done的调用.

我能发现的问题是你没有定义一个processdone信号.Qt不存在该信号.检查我离开的链接,了解自定义信号.同时你可以添加:

class MyProcess(QThread):
    processdone = QtCore.pyqtSignal("QString")
Run Code Online (Sandbox Code Playgroud)

在课程开始时.

最后一件事,但非常重要.您没有使用GUI,但您仍在使用QObjects和Qt信号机制,这取决于主要的Qt循环.因此,QApplication尽管您的应用程序是非gui程序,您仍然需要一个对象.

这是您的代码,现在正在运行:

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

class MyProcess(QThread):
    processdone = QtCore.pyqtSignal("QString") # Define custom signal.
    def __init__(self, parent = None):
        QThread.__init__(self, parent)
    def run(self):
        print("do time intensive process here")
        self.emit( SIGNAL('processdone'), "emitting signal processdone")
        return       

class MyClass(QObject):

    def __init__(self, parent=None):            # All QObjects receive a parent argument (default to None)
        super(MyClass, self).__init__(parent)   # Call parent initializer.

        thread1 = MyProcess(self) 
        self.connect( thread1, SIGNAL("processdone"), self.thread1done)    
        thread1.start()  

    @QtCore.pyqtSlot("QString")         # Tell Python this is a QTSLOT an receives a string
    def thread1done(self, text):
        print(text)                     # Print the text from the signal.

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)  # You still need a QApplication object.
    a = MyClass()
    sys.exit(app.exec())
Run Code Online (Sandbox Code Playgroud)