Python PyQt:是否可以将 QThread 与非 GUI 程序一起使用? [英] Python PyQt: Is it possible to use QThread with a non-GUI program?

查看:69
本文介绍了Python PyQt:是否可以将 QThread 与非 GUI 程序一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a Python PyQt application that displays a simple UI. When the user clicks a button in the UI it triggers a QThread. The use of a thread prevents the UI from "freezing" while the thread runs. I emit signals to pass information from the run thread back to the UI for status updates and to indicate completion. Everything works fine as described and I've created a simple class for my UI to call which creates the thread and runs my generic processing.

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

However, I would also like to create a command line version (No GUI) of my program and use the same processing QThread class. However, I get the following error when I try to connect my signals. It would seem that QThread was only meant for GUI programs?

AttributeError: MyClass instance has no attribute 'connect'

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

Is it possible to use QThread with a non-GUI program?

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.

The problem isn't QThread, the problem is that you're calling the connect method from a class which doesn't have it. You need to make MyClass inherits from QObject.

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

In the GUI this works because whatever widget you're working with (QDialog, QMainWindow, QWidget ...) it inherits (directly or indirectly) from QObject.

要使 MyClassQObject 继承,你只需要:

To make MyClass inherit from QObject you only have to:

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... 

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

除了调用 processdone 信号外,一切正常,但显然它永远不会触发对 thread1done 的调用.

Everything works except the processdone signal is called but apparently it never triggers call to thread1done.

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

The problem I can spot is you don't have defined a processdone signal. That signal does not exist for Qt. Check the link I left you to learn about custom signals. Meanwhile you can add:

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

在课程开始时.

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

And one last thing, but very important. You aren't working with GUI, but you are still using QObjects and the Qt singal mechanisms, which depends on the main Qt loop to work. Hence, you still need a QApplication object despite of your application is a non-gui program.

这是您的代码,现在可以使用了:

Here is your code, now working:

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

这篇关于Python PyQt:是否可以将 QThread 与非 GUI 程序一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆