针对类实现 QProgressBar
Posted
技术标签:
【中文标题】针对类实现 QProgressBar【英文标题】:Implementing QProgressBar against a class 【发布时间】:2014-08-30 14:26:51 【问题描述】:我的 PyQt 程序有 2 个小部件(选择文件等),然后是一个显示解析文件结果的主窗口。
该程序适用于小样本文件,但在尝试解析较大的文件时,它会挂起(显示“无响应”),然后在大约 30 秒左右后显示结果。
我想在主窗口打开之前实现一个 QDialog。 QDialog 将有一个进度条,让用户知道主窗口何时打开。
这个进度条需要设置为主窗口弹出前的时间长度。
实现这一点的最佳方法是什么?我看过一些例子,但进度条只是设置为标准化时间,而不是处理(解析)完成时。
我目前有以下打开主窗口的代码。
def openWidgetMain(self):
self.WidgetMain = WidgetMain()
self.WidgetMain.show()
self.close()
此窗口的所有处理都在它打开时完成。那么如何连接 QProgressBar?
【问题讨论】:
【参考方案1】:将您的持久过程放在某种线程中。阅读:http://qt-project.org/doc/qt-5/threads-technologies.html 从该线程发出信号以更新您的进度条。这样您的应用程序就不会挂起,并且用户可以看到进度。
但是,由您的加载例程决定在进度条中显示哪个百分比。如果您无法计算出准确的百分比,请尝试某种估计(例如,基于文件大小与文件处理量)。
【讨论】:
【参考方案2】:首先,实现这一点的最佳方法是,您必须估计您的加载进度文件。接下来,使用QtCore.QThread
实现它以创建后台进程。最后,将您的回电进度放入您的QtGui.QMainWindow
。
小例子;
import sys
import time
from PyQt4 import QtGui
from PyQt4 import QtCore
class QCustomThread (QtCore.QThread):
startLoad = QtCore.pyqtSignal(int)
progressLoad = QtCore.pyqtSignal(int)
statusLoad = QtCore.pyqtSignal(bool)
def __init__ (self, parentQWidget = None):
super(QCustomThread, self).__init__(parentQWidget)
self.wasCanceled = False
def run (self):
# Simulate data load estimation
numberOfprogress = 100
self.startLoad.emit(numberOfprogress)
for progress in range(numberOfprogress + 1):
# Delay
time.sleep(0.1)
if not self.wasCanceled:
self.progressLoad.emit(progress)
else:
break
self.statusLoad.emit(True if progress == numberOfprogress else False)
self.exit(0)
def cancel (self):
self.wasCanceled = True
class QCustomMainWindow (QtGui.QMainWindow):
def __init__ (self):
super(QCustomMainWindow, self).__init__()
# Create action with QPushButton
self.startQPushButton = QtGui.QPushButton('START')
self.startQPushButton.released.connect(self.startWork)
self.setCentralWidget(self.startQPushButton)
# Create QProgressDialog
self.loadingQProgressDialog = QtGui.QProgressDialog(self)
self.loadingQProgressDialog.setLabelText('Loading')
self.loadingQProgressDialog.setCancelButtonText('Cancel')
self.loadingQProgressDialog.setWindowModality(QtCore.Qt.WindowModal)
def startWork (self):
myQCustomThread = QCustomThread(self)
def startLoadCallBack (numberOfprogress):
self.loadingQProgressDialog.setMinimum(0)
self.loadingQProgressDialog.setMaximum(numberOfprogress)
self.loadingQProgressDialog.show()
def progressLoadCallBack (progress):
self.loadingQProgressDialog.setValue(progress)
def statusLoadCallBack (flag):
print 'SUCCESSFUL' if flag else 'FAILED'
myQCustomThread.startLoad.connect(startLoadCallBack)
myQCustomThread.progressLoad.connect(progressLoadCallBack)
myQCustomThread.statusLoad.connect(statusLoadCallBack)
self.loadingQProgressDialog.canceled.connect(myQCustomThread.cancel)
myQCustomThread.start()
myQApplication = QtGui.QApplication(sys.argv)
myQCustomMainWindow = QCustomMainWindow()
myQCustomMainWindow.show()
sys.exit(myQApplication.exec_())
QtCore.QThread
的更多信息(推荐阅读以了解行为)
【讨论】:
以上是关于针对类实现 QProgressBar的主要内容,如果未能解决你的问题,请参考以下文章
通过使用GDI+和CImage类配合实现针对目标窗体的子控件进行截图
Java:通用的排序工具类,能够对自定义对象,针对不同的属性(字段),实现排序(正序倒序)
JAVA:事件监听器之WindowAdapter类(针对窗口事件)