进度对话框QProgressDialog
进度对话框 QProgressDialog 用于表明某项任务正在进行及任务的完成进度。
进度对话框的界面如图所示,由 1个标签 QLabel1个进度条 QProgressBar 和 1个按钮QPushButton 构成。
进度对话框可以与定时器一起工作每隔一段时间获取一项任务的完成值,再设置进度条的当前值。当然,如果任务能自动输出其完成值,可直接与进度条的槽函数setValue(int)连接。
用QProgressDialog 类创建进度对话框的方法如下所示:
- 第1个 str 是进度对话窗口的标题栏
- 第 2个 str 是签的文本
- 第 1个 int 是进度条的最小值
- 第2个int 是进度条的最大值。
from PySide6.QtWidgets import QProgressDialog
QProgressDialog(labelText: str,cancelButtonText: str,minimum: int,maximum: int,parent: Union[PySide6.QtWidgets.QWidget,NoneType]=None,flags: PySide6.QtCore.Qt.WindowType=Default(Qt.WindowFlags))-> None
QProgressDialog(parent: Union[PySide6.QtWidgets.QWidget,NoneType]=None,flags: PySide6.QtCore.Qt.WindowType=Default(Qt.WindowFlags))-> None
进度对话框QProgressDialog 的属性
属性 | 描述 | 访问功能 |
---|---|---|
autoClose: bool | 此属性保存对话框是否被reset()隐藏。 默认值为true。 | autoClose() setAutoClose(close) |
autoReset: bool | 此属性保存进度对话框是否在value()等于maximum()时立即调用reset()。 默认值为true。 | autoReset() setAutoReset(reset) |
labelText: str | 此属性包含标签的文本。 默认文本是一个空字符串。 | labelText() setLabelText(text) |
maximum: int | 此属性包含由进度条表示的最高值。 默认值为100。 | maximum() setMaximum(maximum) |
minimum: int | 此属性包含由进度条表示的最低值。 默认值为0。 | minimum() setMinimum(minimum) |
minimumDuration: int | 此属性保存对话框出现之前必须经过的时间。 如果任务的预期持续时间小于最小持续时间,则根本不会出现对话框。这样可以防止快速结束的任务弹出对话框。对于预计超过最小持续时间的任务,该对话框将在最小持续时间之后或设置任何进度后立即弹出。 如果设置为0,则只要设置了任何进度,就会始终显示对话框。默认值为4000毫秒。 | minimumDuration() setMinimumDuration(ms) |
value: int | 此属性保存当前已完成的进度。。 为了使进度对话框按预期工作,您应该首先将此属性设置为minimum(),最后将其设置为maximum();您可以在两者之间多次调用setValue()。 | value() setValue(progress) |
wasCanceled: bool | 此属性保存对话框是否已取消。 | wasCanceled() |
进度对话框QProgressDialog 的常用方法
进度对话框 QProgressDialog 的常用方法如表所示:
QProgressDialog的方法及参数类型 | 返回值的类型 | 说 明 |
---|---|---|
setMinimumDuration(int) | None | 设置对话框从创建到显示出来的过渡时间 |
minimumDuration() | int | 获取从创建到显示时的时间 |
[slot]setValue(int) | None | 设置进度条的当前值 |
value | int | 获取进度条的当前值 |
[slot]setMaximum(int) | None | 设置进度条的最大值 |
maximum() | int | 获取进度条的最大值 |
[slot]setMinimum(int) | None | 设置进度条的最小值 |
minimum() | int | 获取进度条的最小值 |
[slot]setRange(minimum:int,maximum :int) | None | 设置进度条的最小值和最大值 设置进度对话框的最小和最大值 如果最大值小于最小值,则最小值将成为唯一的合法值。 如果当前值超出新范围,则使用reset()重置进度对话框。 |
[slot]setLabelText(str) | None | 设置对话框中标签的文本 |
setLabel(QLabel) | None | 将标签设置为QLabel。进度对话框将根据需要调整大小。标签将归进度对话框所有,并将在必要时删除,因此不要传递堆栈上对象的地址。 |
labelText() | Str | 获取进度条中标签的文本 |
[slot]cancel() | Str | 重置进度对话框。wasCanceled()变为true,直到重置进度对话框。进度对话框将隐藏。 |
wasCanceled() | bool | 获取对话框是否被取消了 |
[slot]forceShow() | None | 如果在算法启动并且经过最小持续时间毫秒后对话框仍处于隐藏状态,则显示该对话框。 |
[slot]reset() | None | 重置进度对话框。如果autoClose()为true,则进度对话框将隐藏。 |
setAutoClose(bool) | None | 调用reset()方法时,设置是否自动隐藏autoClose |
autoClose() | 6001 | 获取是否自动隐藏 |
setAutoReset(bool) | None | 进度条的值达到最大时,设置是否自动重置 |
autoReset() | bool | 获取进度条的值达到最大时,是否自动重置 |
setBar(QProgressBar:PySide6.QtWidgets.QProgressBar) | None | 将进度条小部件设置为条形。进度对话框将根据需要调整大小。进度对话框拥有进度条的所有权,进度条将在必要时删除,因此不要使用堆栈上分配的进度条。 |
[slot]setCancelButtonText(str) | None | 将取消按钮的文本设置为cancelButtonText。如果文本设置为QString(),则会导致取消按钮被隐藏并删除。 |
setCancelButton(QPushButton:PySide6.QtWidgets.QPushButton) | None | 将取消按钮设置为按钮cancelButton。进度对话框拥有该按钮的所有权,该按钮将在必要时删除,因此不要传递堆栈上对象的地址,即使用new()创建按钮。如果"无"通过,则不会显示取消按钮。 |
open(receiver:PySide6.QtCore.QObject,member:str) | 打开对话框并将其cancelled()信号连接到接收器和成员指定的插槽。 当对话框关闭时,信号将从插槽断开。 |
进度对话框 QProgressDialog方法介绍如下:
- 进度对话框显示
- 进度对话框显示可以不用show()等方法来显示在创建进度对话后,经过某段时间后对话框会自动显示出来,这段时间是通过 setMinimumDuration(int)来设置的。参数 int 的单位是毫秒,默认是 4000 毫秒如果设置为0,则立即显示对话。
- 可以forceShow()方法强制显示对话框。设置这个显示时间的目的是防止任务进展大快,进度对话框一闪而过。
- 进度条需要设置最小值和最大值及当前值
- 最小值和最大值分别用setMinimum(int)方法和 setMaximum(int)方法设置默认是0和100;
- 进度条的最小值和最大值也可以用setRange(int,int)方法来设置。
- 进度条的当前值用setValue(int)方法设置。
- 进度条上显示的百分比用公式(valueminumum)/(maximum-minimum)来计算,
- 对话框如果设置了 setAutoClose(True),调用reset()方法重置进度条时,会自动隐藏对话框。
- 对话框如果设置了 setAutoReset(True)则进度条的值达到最大值时会调用reset()方法重置进度条;如果设置了 setAutoClose(True),会隐藏对话框
- 用setLabelText(str)方法和 setCancelButtonText(str)方法可以设置对话框中标签和按钮显示的文字
- 当单击对话框中的 Cancel 按钮或执行 cancel()方法时会取消对话框,并且会重置和隐藏对话框,同时 wasCanceled()的值为 True。
进度对话框用于向用户指示操作需要多长时间,并证明应用程序尚未冻结。它还可以为用户提供中止操作的机会。
进度对话框的一个常见问题是很难知道何时使用它们;操作在不同的硬件上花费不同的时间。QProgressDialog为这个问题提供了一个解决方案:它估计操作将花费的时间(基于步骤的时间),并且只有当估计值超过minimumDuration()(默认为4秒)时才会显示自己。
使用setMinimum()和setMaximum()或构造函数设置操作中的"步数",并在操作进行时调用setValue()。步骤的数量可以任意选择。它可以是复制的文件数、接收的字节数、通过算法主循环的迭代次数,也可以是其他合适的单位。进度从setMinimum()设置的值开始,当您使用setMaximum()设置值作为参数调用setValue()时,进度对话框显示操作已经完成。
该对话框会在操作结束时自动重置并隐藏自己。使用setAutoReset()和setAutoClose()可以更改此行为。请注意,如果您设置了一个新的最大值(使用setMaximum()或setRange()),该值等于当前值(),则无论怎样,对话框都不会关闭。
有两种使用QProgressDialog的方法:模态和非模态。
与非模态QProgressDialog相比,模态QProgress Dialog更易于程序员使用。在循环中执行操作,每隔一段时间调用setValue(),然后使用wasCanceled()检查是否取消。例如:
progress = QProgressDialog("Copying files...","Abort Copy",0,numFiles,self)
progress.setWindowModality(Qt.WindowModal)
for i in range(0,numFiles):
progress.setValue(i)
if progress.wasCanceled():
break
#... copy one file
progress.setValue(numFiles)
无模式进度对话框适用于在后台进行的操作,用户可以在后台与应用程序交互。这样的操作通常基于QTimer(或timerEvent())或QSocketNotifier;或者在单独的线程中执行。主窗口状态栏中的QProgressBar通常是非模式进度对话框的替代方案。
您需要有一个事件循环来运行,将cancelled()信号连接到一个停止操作的插槽,并每隔一段时间调用setValue()。例如:
# Operation constructor
def __init__(self,parent):
super().__init__(parent)
self.steps = 0
pd = QProgressDialog("Operation in progress.","Cancel",0,100)
pd.canceled.connect(self.cancel)
t = QTimer(self)
t.timeout.connect(self.perform)
t.start(0)
在这两种模式下,可以通过使用setLabel()、setBar()和setCancelButton()将子窗口小部件替换为自定义窗口小部件来自定义进度对话框。函数setLabelText()和setCancelButtonText()设置显示的文本。
进度对话框QProgressDialog 的信号
进度对话框 QProgressDialog 只有一个信号 canceled(),单击对话中的 Cancel 按时发送信号。
进度对话框QProgressDialog 的应用实例
下面的程序将进度对话框和定时器相结合,定时器每隔 200 毫秒发送一个信息。进度条的值随时间的推移逐渐增大,当超过进度条的最大值或单击 Cancel 按钮后,进度条被隐藏和重置。
import sys
from PySide6.QtWidgets import QApplication,QWidget,QProgressDialog
from PySide6.QtCore import QTimer
class MyWindow(QWidget):
def __init__(self,parent=None):
super().__init__(parent)
self.pd=QProgressDialog("Copying...","Cancel",0,100,self)
self.pd.canceled.connect(self.cancel)
self.t=QTimer(self)
self.t.setInterval(200)
self.t.timeout.connect(self.perform)
self.t.start()
self.steps=0
def perform(self):
self.pd.setValue(self.steps)
self.steps=self.steps + 1
if self.steps > self.pd.maximum():
self.t.stop()
def cancel(self):
self.t.stop()
self.close()
if __name__=='__main__':
app=QApplication(sys.argv)
window=MyWindow()
window.show()
sys.exit(app.exec())
QProgressDialog(Bar)例2
# -*- coding: UTF-8 -*-
# File date: Hi_2023/3/14 23:29
# File_name: 03-QProgressDialog(Bar)例子.py
from PySide6.QtCore import Qt.QTimer
from PySide6.QtWidgets import *
import sys
import time
class Main(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("QProgressDialog Demo")
widget = QWidget()
self.setCentralWidget(widget)
layout = QVBoxLayout()
widget.setLayout(layout)
self.label = QLabel('显示进度条取消信息')
layout.addWidget(self.label)
button_modeless = QPushButton('显示无模式进度条,不会阻断其他窗口',self)
button_modeless.clicked.connect(self.show_modeless)
layout.addWidget(button_modeless)
button_model = QPushButton('模式进度条,会阻断其他窗口',self)
button_model.clicked.connect(self.show_modal)
layout.addWidget(button_model)
button_auto = QPushButton('不会自动关闭和重置的进度条',self)
button_auto.clicked.connect(self.show_auto)
layout.addWidget(button_auto)
# 自定义进度条,
button_custom = QPushButton('自定义QProgressDialog',self)
button_custom.clicked.connect(self.show_custom)
layout.addWidget(button_custom)
# 水平滑块
self.pd_slider = QProgressDialog("滑块进度条:点击滑块我会动","Cancel",10,100,self)
self.pd_slider.move(300,400)
self.pd_slider.canceled.connect(lambda: self.cancel(self.pd_slider))
self.slider_horizon = QSlider(Qt.Horizontal)
self.slider_horizon.setRange(10,120)
layout.addWidget(self.slider_horizon)
self.slider_horizon.valueChanged.connect(lambda: self.valuechange(self.slider_horizon))
bar = QProgressBar(self)# QProgressBar
bar.valueChanged.connect(lambda value: print('自定义Bar的Value值:',value))
bar.setRange(1,80)
self.slider_horizon.valueChanged.connect(lambda value: bar.setValue(value))
layout.addWidget(bar)
# self.slider_horizon.valueChanged.connect(self.pd_slider.setValue)
self.resize(300,200)
def show_modeless(self):
pd_modeless = QProgressDialog("无模式进度条:可以操作父窗口","Cancel",0,12)
pd_modeless.move(300,600)
self.steps = 0
def perform():
pd_modeless.setValue(self.steps)
self.label.setText('当前进度条值: {}\n最大值: {}\n是否取消(重置)过进度条: {}'.format(pd_modeless.value(),pd_modeless.maximum(),pd_modeless.wasCanceled()))
# // perform one percent of the operation
self.steps += 1
if self.steps > pd_modeless.maximum():
self.timer.stop()
self.timer = QTimer(self)
self.timer.timeout.connect(perform)
self.timer.start(1000)
pd_modeless.canceled.connect(lambda: self.cancel(pd_modeless))
pd_modeless.canceled.connect(self.timer.stop)
def show_modal(self):
max = 10
pd_modal = QProgressDialog("模式进度条:不可以操作父窗口","终止",0,max,self)
pd_modal.move(300,600)
pd_modal.setWindowModality(Qt.WindowModal)
# pd_modal.setWindowModality(Qt.ApplicationModal)
pd_modal.setMinimumDuration(1000)# 一秒后出现对话框
# 信号和槽要放在计时器后面,否则不会被执行
pd_modal.canceled.connect(lambda: self.cancel(pd_modal))
for i in range(max + 1):
pd_modal.setValue(i)
self.label.setText('当前进度条值: {}\n最大值: {}\n是否取消(重置)过进度条: {}'.format(pd_modal.value(),pd_modal.maximum(),pd_modal.wasCanceled()))
if pd_modal.value()>= pd_modal.maximum()or pd_modal.wasCanceled():
break
# print('you can do something here')
time.sleep(1)
# pd_modal.setValue(max)
def get_pd_auto(self):
if not hasattr(self,'pd_auto'):
max = 5
self.pd_auto = QProgressDialog("我不会自动关闭和重置,哈哈","终止",0,max,self)
self.pd_auto.move(300,600)
self.pd_auto.setWindowModality(Qt.ApplicationModal)
self.pd_auto.setMinimumDuration(1000)
# self.pd_auto.setValue(0)
self.pd_auto.setAutoClose(False)# 取消满值自动关闭(默认情况下满值自动重置)
self.pd_auto.setAutoReset(False)# 取消自动重置(默认情况下满值自动重置)
self.pd_auto.canceled.connect(lambda: self.cancel(self.pd_auto))
return self.pd_auto
def show_auto(self):
pd_auto = self.get_pd_auto()
for i in range(1000):
if pd_auto.value()>= pd_auto.maximum()or pd_auto.wasCanceled():
self.label.setText('当前进度条值: {}\n最大值: {}\n是否取消(重置)过进度条: {}'.format(pd_auto.value(),pd_auto.maximum(),pd_auto.wasCanceled()))
break
pd_auto.setValue(pd_auto.value()+ 1)
self.label.setText('当前进度条值: {}\n最大值: {}\n是否取消(重置)过进度条: {}'.format(pd_auto.value(),pd_auto.maximum(),pd_auto.wasCanceled()))
# print('you can do something here')
time.sleep(1)
# pd_auto.setValue(max)
def show_custom(self):
pd_custom = QProgressDialog(self)
bar = QProgressBar()
bar.setMaximum(9)
bar.setMinimum(2)
bar.valueChanged.connect(lambda value: print('自定义Bar的Value值:',value))
pd_custom.setBar(bar)
pd_custom.setLabel(QLabel('自定义进度条,使用自定义的QProgressBar'))
pd_custom.setCancelButton(QPushButton('取消按钮'))
pd_custom.move(300,600)
pd_custom.setWindowModality(Qt.WindowModal)
# pd_custom.setWindowModality(Qt.ApplicationModal)
pd_custom.setMinimumDuration(1000)# 一秒后出现对话框
# 信号和槽要放在计时器后面,否则不会被执行
pd_custom.canceled.connect(lambda: self.cancel(pd_custom))
for i in range(-1,bar.maximum()+ 1):
pd_custom.setValue(i)
self.label.setText('当前进度条值: {}\n最大值: {}\n是否取消(重置)过进度条: {}'.format(pd_custom.value(),pd_custom.maximum(),pd_custom.wasCanceled()))
if pd_custom.value()>= pd_custom.maximum()or pd_custom.wasCanceled():
break
# print('you can do something here')
time.sleep(1)
# pd_modal.setValue(max)
def cancel(self,pg):
self.statusBar().showMessage('你手动取消了进度条:"%s"'% pg.labelText(),3000)
def valuechange(self,slider):
size = slider.value()
self.pd_slider.setValue(size)
self.label.setText(
'当前进度条值: {}\n最大值: {}\n是否取消(重置)过进度条: {}'.format(self.pd_slider.value(),self.pd_slider.maximum(),self.pd_slider.wasCanceled()))
if __name__ =="__main__":
app = QApplication(sys.argv)
window = Main()
window.show()
sys.exit(app.exec())