【问题标题】:Python PyQt: Is it possible to use QThread with a non-GUI program?Python PyQt:是否可以将 QThread 与非 GUI 程序一起使用?
【发布时间】:2023-03-06 11:39:01
【问题描述】:

我有一个显示简单 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(或 python 标准库中的 Thread)有一个可以完成工作的类,并且可以用两者来实例化
  • 你能在你的代码中显示 gui 和 nongui 版本之间的区别吗?

标签: python multithreading pyqt pyqt4


【解决方案1】:

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

在课程开始时。

还有最后一件事,但非常重要。您没有使用 GUI,但您仍在使用 QObjects 和 Qt 信号机制,这取决于主 Qt 循环的工作。因此,尽管您的应用程序是非 gui 程序,但您仍然需要一个 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())

【讨论】:

  • 我知道它会像这样简单......我明天会尝试并让你知道它是怎么回事,但我希望这个答案会得到检查。 :)
  • 我在上面添加了代码。从 QObject 继承我应该做哪些改变?我的 GUI 版本有效,因为(如你所说)我继承了 QMainWindow,但我不能在非 GUI 逻辑中使用 QMainWindow。
  • 你并不痛苦,但你必须公平。最初的提示(关于 QThreads)和另一个关于如何继承的问题已经得到解答。不要以为如果你检查答案我会停止帮助你,它恰恰相反。关于你最后的评论,可能是python定义类时__init__方法出了问题。这真的有点难知道,因为我没有你的代码,我无法重现错误。
  • 我发现上一条评论的语法错误。我已经更新了上面的完整工作代码。除了调用 processdone 信号外,一切正常,但显然从未触发对 thread1done 的调用?
  • 您是否阅读了我对新型信号和插槽支持的建议?链接在答案的末尾。我可以发现的问题是您没有定义processdone 信号。 Qt 不存在该信号。查看我留给您的链接,了解自定义信号。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-13
  • 1970-01-01
  • 1970-01-01
  • 2012-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多