Skip to main content
 首页 » 编程设计

python PyQt : Is it possible to use QThread with a non-GUI program

2025年05月04日26zhenyulu

我有一个显示简单 UI 的 Python PyQt 应用程序。 当用户单击 UI 中的按钮时,它会触发 QThread。 使用线程可防止 UI 在线程运行时“卡住”。 我发出信号以将信息从运行线程传递回 UI 以进行状态更新并指示完成。一切都如描述的那样工作正常,我已经为我的 UI 创建了一个简单的类来调用它创建线程并运行我的通用处理。

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

AttributeError: MyClass instance has no attribute 'connect' 

是否可以将 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() 

请您参考如下方法:

问题不在于 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...  

我还建议您使用 New-style Signal and Slot Support .

除调用 processdone 信号外,一切正常,但显然它从未触发对 thread1done 的调用。

我能发现的问题是您没有定义 processdone 信号。 Qt 不存在该信号。查看我留给您的链接以了解自定义信号。同时你可以添加:

class MyProcess(QThread): 
    processdone = QtCore.pyqtSignal("QString") 

在类(class)开始时。

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

这是你的代码,现在可以工作了:

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