经常看到有人问在PyQt里面如何做长操作的时候更新GUI。我自己总结了几种方案,以及他 们的适用场合:
使用processEvents(),适合每次处理时间短的情况,缺点是CPU占用可能很大:
for filename in os.listdir(pathToYourDir): doSomething() updateGui() qApp.processEvents()用QThread,用QMetaObject.invokeMethod()向主线程传递跨线程的信息
class MyWindow(QMainWindow): @pyqtSlot(int) def updateProgress(self, value): self.lblProgress=str(value)class ProcessorThread(QThread): def __init__(self, myWindow): QThread.__init__(self) self.myWindow=myWindow def run(self): for filename in os.listdir(): doSomething() progress=29 #计算百分比 QMetaObject.invokeMethod(self.myWindow, "updateProgress", \ Qt.QueuedConnection, Q_ARG("int", progress)此方案还有一个变种是使用跨线程的signal/slot:
class MyWindow(QMainWindow): def __init__(self): self.processorThread=ProcessorThread() self.processorThread.progressUpdated.connect( \ self.updateProgress, Qt.QueuedConnection) @pyqtSlot(int) def updateProgress(self, value): self.lblProgress=str(value)class ProcessorThread(QThread): progressUpdated=pyqtSignal(int) def __init__(self): QThread.__init__(self) #没有parent参数 self.moveToThread(self) def run(self): for filename in os.listdir(): doSomething() progress=29 #计算百分比 self.progressUpdated.emit(progress)用QProgressDialog。有同步与异步两种方法。先看看同步。
buf=io.StringIO()progress=QProgressDialog(self.trUtf8("打开文件"), \ self.trUtf8("取消"), 0, f.size(), self)progress.setWindowModality(Qt.WindowModal)while not f.atEnd(): data=f.read(1024) text=data.decode(locale.getpreferredencoding()) buf.write(text) progress.setValue(f.pos()) if progress.wasCanceled(): returnself.textEdit.setPlainText(buf.getvalue())progress.setValue(f.size()) #100%的时候对话框自动关掉progress.setParent(None) #清理资源异步与第二种方案类似,但是采用signal/slot,而且不能是模态对话框。
把长的操作分为小的操作,适合每次处理都是异步的或者很复杂的情况
def __init__(self): self.itorator=self.fetchFile() self.timer=QTimer() self.timer.timeout.connect(self.processFile) self.timer.start(0)def fetchFile(self): for filename in os.listdir(pathToYourDir): yield filenamedef processFile(): try: filename=self.itorator.next() doSomething() updateGui() except StopIterator: self.timer.stop()第四种方案不常用,但是当你的处理过程本身是异步的时候就会用到。第一、第二方案都不 错,优点是灵活。第三种方案也常见,优点是模态对话框阻止用户的其它操作,可以随时取 消。缺点是一个对话框挡在那里,相当地影响用户体验。
ps:这些代码不能直接运行。。。差不多懂就好,呵呵
欢迎光临 纳速健身 (https://nasue.com/) | Powered by Discuz! X3.4 |