Python PyQT4和线程:在QThread完成并更新ListWidget后关闭MainWidget
我试图理解Python中线程是如何工作的。因此,我编写了一个应用程序,在一个单独的QThread中安装一些包 一旦worker完成(发出完成的信号),我想等待几秒钟,然后关闭MainWidget(见下文):Python PyQT4和线程:在QThread完成并更新ListWidget后关闭MainWidget,python,multithreading,Python,Multithreading,我试图理解Python中线程是如何工作的。因此,我编写了一个应用程序,在一个单独的QThread中安装一些包 一旦worker完成(发出完成的信号),我想等待几秒钟,然后关闭MainWidget(见下文): def已完成(自): self.installbutton.setEnabled(True) self.listwidget.addItem(QtCore.QString(“流程完成,祝您愉快!”) 时间。睡眠(5) self.close() 现在的问题似乎是,在完成的回调中调用self.
def已完成(自):
self.installbutton.setEnabled(True)
self.listwidget.addItem(QtCore.QString(“流程完成,祝您愉快!”)
时间。睡眠(5)
self.close()
现在的问题似乎是,在完成的回调中调用self.close会导致在窗口关闭之前不再更新ListWidget
我的猜测是,ListWidget和回调函数位于同一个堆栈中,因此ListWidget不再有机会终止。但如何解决这些问题呢
有什么建议可以克服这个问题吗
顺便说一句:我“被迫”使用Python2.7.5和PyQt4,以便与公司的其他部分兼容。。。这就是为什么我用老式的信号
代码如下:
导入系统
导入操作系统
导入时间
导入子流程
导入日志记录
log=logging.getLogger(_名称__)
logging.basicConfig(级别=logging.DEBUG)
从PyQt4导入QtGui、QtCore
def main():
app=QtGui.QApplication(sys.argv)
w=InstallWizzard()
w、 show()
sys.exit(app.exec_())
类InstallWizzard(QtGui.QMainWindow):
def uuu init uuu(self,parent=None):
QtGui.QMainWindow.\uuuuu init\uuuuu(self,parent)
self.centralwidget=QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.thread=Worker()
hlayout=QtGui.QVBoxLayout()
self.listwidget=QtGui.QListWidget()
self.installbutton=QtGui.QPushButton()
self.installbutton.setText(“立即安装兄弟…”)
hlayout.addWidget(self.installbutton)
self.listwidget.addItem(QtCore.QString(r'单击“立即安装兄弟…”开始安装“))
self.centralwidget.setLayout(hlayout)
self.connect(self.installbutton,QtCore.SIGNAL(“clicked()”),self.\u安装开始时)
self.connect(self.thread,QtCore.SIGNAL(“finished()”),self.finished)
#self.connect(self.thread,QtCore.SIGNAL(“terminated()”),self.updateUI)
self.connect(self.thread,QtCore.SIGNAL(“install_mssg(QString)”),self.\u cmd\u processed)
hlayout.addWidget(self.listwidget)
def_cmd_已处理(自身、mssg):
self.listwidget.addItem(QtCore.QString(mssg))
def_on_安装_启动(自):
self.installbutton.setEnabled(False)
cmds=[(“安装comtypes”,r'easy_install comtypes')]
self.thread.install(cmds)
def完成(自我):
self.installbutton.setEnabled(True)
self.listwidget.addItem(QtCore.QString(“流程完成,祝您愉快!”)
时间。睡眠(5)
self.close()
类工作程序(QtCore.QThread):
def uuu init uuu(self,parent=None):
QtCore.QThread.\uuuuu init\uuuuu(self,parent)
打印(“已启动的工作人员…”)
def安装(自我,cmds):
self.cmds=cmds
self.start()
def运行(自):
对于desc,self.cmds中的cmd:
self.emit(QtCore.SIGNAL(“安装”)QtCore.QString(desc+“:…”)
尝试:
self.\u write\u cmd\u行(cmd)
mssg=“…成功”
例外情况除外,如e:
mssg=QtCore.QString(str(“…Faillure:+e))
自我发射(QtCore.SIGNAL(“install_mssg(QString)”),mssg)
打印(“来自工人的ond TSCHASS”)
定义(自我):
self.quit()
self.wait()
定义写入命令行(self,cmd):
p=subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE,shell=True)
a、 b=p.沟通()
如果a中的“无法”或a中的“错误”或a中的“无法识别”:
errormssg=“无法处理cmd!”
记录错误(ERRORMSG)
引发异常(错误MSSG)
其他:
logging.debug(str(cmd)+“successful”)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()
阅读您的问题和代码后。。在理解中,您有两个线程:主线程和工作线程,当您的工作线程完成时(我的意思是,这里的线程已到达代码的最后一行),您希望通知主线程关闭工作线程并切换到另一个窗口(可能)或执行其他操作 要做到这一点,显然需要与UI线程(主线程)通信,因此需要在工作者(线程)类中添加这几行代码
signal = QtCore.pyqtSignal(str) # Create a signal
然后转到线程的最后一行,确保当工作人员到达该行时,工作将完成,并添加这一行以通知主线程
self.signal.emit('Some String here') # this will send the string over the signal to your UI thread
现在跳转到InstallWizzard类**并添加以下行
在\uuuu init\uuuuu方法中,在**self.thread=Worker()下面添加这一行。
现在,在您完成的方法中,您可以终止/关闭/退出您正在使用的方法
self.thread.quit() # as you might guessed this will quit your thread.
如果要强制关闭工作进程,也可以将quit()替换为terminate(),但请阅读QThread::terminate:
警告:此功能很危险,不鼓励使用。这个
线程可以在其代码路径中的任意点终止。线程可以是
在修改数据时终止。这根线没有机会断开
清理后,自己,解锁任何持有的互斥等简而言之,使用
此功能仅在绝对必要时使用
如果您关心将通过Worker的信号发送的字符串,请向您完成的方法添加新参数以访问该字符串。
就是这样:)
我知道我现在回答你的问题已经太晚了(1年前),但这可能对其他开发人员有所帮助……无论如何,如果你是
self.thread.quit() # as you might guessed this will quit your thread.