经常看到有人问在PyQt里面如何做长操作的时候更新GUI。我自己总结了几种方案,以及他们的适用场合:

发布时间:2014-10-23 23:23:06
来源:分享查询网

经常看到有人问在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, "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():          return  self.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 filename  def processFile():      try:          filename=self.itorator.next()          doSomething()          updateGui()      except StopIterator:          self.timer.stop()  第四种方案不常用,但是当你的处理过程本身是异步的时候就会用到。第一、第二方案都不错,优点是灵活。第三种方案也常见,优点是模态对话框阻止用户的其它操作,可以随时取消。缺点是一个对话框挡在那里,相当地影响用户体验。  ps:这些代码没有调试过。。。差不多懂就好,呵呵 

返回顶部
查看电脑版