Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Qthread不工作,GUI仍挂起_Qt_Pyqt_Qthread - Fatal编程技术网

Qthread不工作,GUI仍挂起

Qthread不工作,GUI仍挂起,qt,pyqt,qthread,Qt,Pyqt,Qthread,我试图用pyqt实现一个线程的基本示例,其中有一个文本框,在处理一些代码时会定期更新。我试图删除任何不必要的依赖项,并尽可能地抽象代码,所以我只是用一个while循环来替换要在后台处理的代码,该循环在文本框读取的每个周期发送数据。但是,它不起作用,我不知道是什么导致UI挂起。我为当前线程id添加了调试语句,并且main和worker类(在我的示例中称为Process)都匹配 #!/zin/tools/bin/python #vim:expandtab filetype=python nocind

我试图用pyqt实现一个线程的基本示例,其中有一个文本框,在处理一些代码时会定期更新。我试图删除任何不必要的依赖项,并尽可能地抽象代码,所以我只是用一个while循环来替换要在后台处理的代码,该循环在文本框读取的每个周期发送数据。但是,它不起作用,我不知道是什么导致UI挂起。我为当前线程id添加了调试语句,并且main和worker类(在我的示例中称为Process)都匹配

#!/zin/tools/bin/python
#vim:expandtab filetype=python nocindent sw=4

import sys, traceback
import os
import subprocess
import time 
from PyQt4 import QtCore,QtGui


try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    _fromUtf8 = lambda s: s

class Process (QtCore.QObject):
    processCmdDone = QtCore.pyqtSignal()
    processdataReady = QtCore.pyqtSignal(str)

    def __init__(self):
        super(Process, self).__init__()
        self.processdataReady.connect(self.debug)

    def debug(self):
        print  "signal process data ready is invoked from within the process"

    @QtCore.pyqtSlot()
    @QtCore.pyqtSlot(str)
    def execCmd(self):
        print 'worker thread id :'+ str (QtCore.QThread.currentThreadId())
        x = 0
        while x < 100:
            x+=1
            self.processdataReady.emit(str(x)+'\n')
            time.sleep(1)
        self.processCmdDone.emit()
        print "process ended"


class MainWindow (QtGui.QWidget):
    def __init__(self,filename = None, parent=None):
        super(MainWindow,self).__init__(parent)
        self.transcript_textEdit = QtGui.QTextBrowser()
        font = QtGui.QFont()
            font.setPointSize(12)
            self.transcript_textEdit.setFont(font)
            self.transcript_textEdit.setObjectName(_fromUtf8("transcript_textEdit"))
            self.layout = QtGui.QVBoxLayout(self)
            self.layout.addWidget(self.transcript_textEdit)

        self.run_pushButton = QtGui.QPushButton()
            self.run_pushButton.setFont(font)
            self.run_pushButton.setObjectName(_fromUtf8("run_pushButton"))
            self.run_pushButton.setText('Run')
            self.layout.addWidget(self.run_pushButton)
            self.run_pushButton.clicked.connect(self.execCmdThreading)

    def dataReady(self,text):

        cursor = self.transcript_textEdit.textCursor()
        cursor.movePosition(cursor.End)
        cursor.insertText(str(text))
        self.transcript_textEdit.ensureCursorVisible()


    def execCmdThreading(self):
        print 'gui thread id :'+ str (QtCore.QThread.currentThreadId())
        thread = QtCore.QThread(self)
        process_inst = Process()
        process_inst.moveToThread(thread)
        process_inst.processdataReady.connect(self.dataReady)
        process_inst.processCmdDone.connect(thread.quit)
        thread.finished.connect(thread.deleteLater)
        process_inst.processCmdDone.connect(process_inst.deleteLater)
        thread.started.connect(lambda: process_inst.execCmd())
        thread.start()



if __name__=="__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindowInst = MainWindow()
    MainWindowInst.show()
    sys.exit(app.exec_())
#/zin/tools/bin/python
#vim:expandtab文件类型=python nocindent sw=4
导入系统,回溯
导入操作系统
导入子流程
导入时间
从PyQt4导入QtCore、QtGui
尝试:
_fromUtf8=QtCore.QString.fromUtf8
除属性错误外:
_fromUtf8=λs:s
类进程(QtCore.QObject):
processCmdDone=QtCore.pyqtSignal()
processdataReady=QtCore.pyqtSignal(str)
定义初始化(自):
超级(进程,自我)。\uuuu初始化
self.processdataReady.connect(self.debug)
def调试(自):
打印“从流程内调用信号流程数据就绪”
@QtCore.pyqtSlot()
@QtCore.pyqtSlot(str)
def execCmd(自我):
打印“工作线程id:”+str(QtCore.QThread.currentThreadId())
x=0
当x<100时:
x+=1
self.processdataReady.emit(str(x)+'\n')
时间。睡眠(1)
self.processCmdDone.emit()
打印“进程结束”
类主窗口(QtGui.QWidget):
def u uu init uu uu(self,filename=None,parent=None):
超级(主窗口,自我)。\uuuuu初始化\uuuuuuu(父级)
self.transcript_textEdit=QtGui.QTextBrowser()
font=QtGui.QFont()
字体设置点大小(12)
self.transcript\u textEdit.setFont(字体)
self.transcript\u textEdit.setObjectName(\u fromUtf8(“transcript\u textEdit”))
self.layout=QtGui.QVBoxLayout(self)
self.layout.addWidget(self.transcript\u textEdit)
self.run_pushButton=QtGui.QPushButton()
self.run_按钮.setFont(字体)
self.run\u butdown.setObjectName(\u fromUtf8(“run\u butdown”))
self.run\u按钮.setText('run'))
self.layout.addWidget(self.run\u按钮)
self.run_按钮。点击。连接(self.execcmd)
def数据就绪(自身,文本):
cursor=self.transcript\u textEdit.textCursor()
cursor.movePosition(cursor.End)
游标.插入文本(str(text))
self.transcript_textEdit.ensurercursorvisible()
def execCmdThreading(自):
打印“gui线程id:”+str(QtCore.QThread.currentThreadId())
thread=QtCore.QThread(self)
过程安装=过程()
进程安装移动到线程(线程)
process\u inst.processdataReady.connect(self.dataReady)
process\u inst.processCmdDone.connect(thread.quit)
thread.finished.connect(thread.deleteLater)
process\u inst.processCmdDone.connect(process\u inst.deleteLater)
thread.started.connect(lambda:process\u inst.execCmd())
thread.start()
如果名称=“\uuuuu main\uuuuuuuu”:
导入系统
app=QtGui.QApplication(sys.argv)
MainWindowInst=MainWindow()
MainWindowInst.show()
sys.exit(app.exec_())
我只是简单地创建了一个文本框和一个按钮,点击按钮后,为类'Process'的inst创建了一个线程,在这里它被移动到tothread,它的方法'execCmd'被执行。执行execCmd方法时,会发出一个信号“processdataReady”,该信号预期将在创建的文本框中显示文本。但是,代码似乎没有按预期运行,UI确实挂起了


我真的非常感谢这里的任何人的帮助。

您正在连接
线程。已启动
信号到lambda:

thread.started.connect(lambda: process_inst.execCmd())
在这里使用可调用的普通python将始终导致在gui线程中处理信号。这是可以理解的,因为可调用(lambda)不像QObjects那样具有线程亲和力。然后从lambda中同步执行
process\u inst.execCmd
方法,不管对象具有什么线程亲缘关系。因此,GUI线程将阻塞

如果希望在worker threads事件lopp中接收和处理信号,请将其直接连接到插槽

要使其正常工作,您还需要确保保留对
过程说明的引用,否则它将在超出范围时被销毁

通过这些调整,您的程序适合我:

...
thread.started.connect(process_inst.execCmd)
thread.process_inst = process_inst
...