栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

PyQt ProgressBar

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

PyQt ProgressBar

您需要允许在循环运行时处理事件,以便应用程序可以保持响应状态。

更重要的是,对于长时间运行的任务,您需要提供一种让用户在循环开始后就停止循环的方法。

一种简单的方法是使用计时器启动循环,然后在循环运行时定期调用qApp.processEvents。

这是一个演示脚本,可以执行此操作:

import sys, timefrom PyQt4 import QtGui, QtCoreclass ProgressBar(QtGui.QWidget):    def __init__(self, parent=None, total=20):        super(ProgressBar, self).__init__(parent)        self.progressbar = QtGui.QProgressBar()        self.progressbar.setMinimum(1)        self.progressbar.setMaximum(total)        self.button = QtGui.QPushButton('Start')        self.button.clicked.connect(self.handleButton)        main_layout = QtGui.QGridLayout()        main_layout.addWidget(self.button, 0, 0)        main_layout.addWidget(self.progressbar, 0, 1)        self.setLayout(main_layout)        self.setWindowTitle('Progress')        self._active = False    def handleButton(self):        if not self._active: self._active = True self.button.setText('Stop') if self.progressbar.value() == self.progressbar.maximum():     self.progressbar.reset() QtCore.QTimer.singleShot(0, self.startLoop)        else: self._active = False    def closeEvent(self, event):        self._active = False    def startLoop(self):        while True: time.sleep(0.05) value = self.progressbar.value() + 1 self.progressbar.setValue(value) QtGui.qApp.processEvents() if (not self._active or     value >= self.progressbar.maximum()):     break        self.button.setText('Start')        self._active = Falseapp = QtGui.QApplication(sys.argv)bar = ProgressBar(total=101)bar.show()sys.exit(app.exec_())

更新

假设您使用的是python的C实现(即CPython),则此问题的解决方案 完全
取决于必须与GUI并行运行的任务的性质。从根本上讲,它是由具有全局解释器锁(GIL)的CPython确定的。

我不会尝试对CPython的GIL进行任何解释:相反,我只建议您观看Dave
Beazley的这段出色的PyCon视频,然后就此结束。


通常,在尝试与后台任务同时运行GUI时,要问的第一个问题是:任务是IO绑定还是CPU绑定?

如果是IO绑定的(例如,访问本地文件系统,从Internet下载等),则该解决方案通常非常简单,因为CPython始终为I /
O操作发布GIL。后台任务可以简单地以异步方式完成,也可以由工作线程执行,而无需执行任何特殊操作即可使GUI保持响应。

当遇到第二个问题要问时,主要的困难出现在与CPU绑定的任务上:可以将任务分解为一系列小步骤吗?

如果可以,那么解决方案是定期向GUI线程发送请求,以处理其当前的未决事件堆栈。上面的演示脚本是该技术的粗略示例。通常,任务将在单独的工作线程中执行,当任务的每个步骤完成时,该线程会发出gui更新信号。(注意:重要的是要确保工作线程自己绝不要尝试任何与GUI相关的操作)。

但是,如果 不能 将任务分解成小步,那么所有常规的线程类型解决方案都将无法正常工作。无论是否使用线程,GUI都将冻结直到任务完成。

对于此最终方案,唯一的解决方案是使用单独的 进程
,而不是单独的线程-即,使用多处理模块。当然,只有目标系统具有多个可用的CPU内核时,此解决方案才有效。如果只有一个CPU内核可以使用,那么基本上没有什么可以提供帮助的(除了切换到Python的不同实现,或者完全切换到另一种语言)。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/639465.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号