15-窗口、窗口控件、对话框以及相关功能类-进度对话框QProgressDialog

QProgressDialog是Qt库中的一个组件,用于显示任务进度,通常包含标签、进度条和取消按钮。它可以根据任务的预期持续时间决定是否显示,避免快速任务导致对话框闪烁。用户可以设置最小值、最大值和当前值,并通过定时器更新进度。QProgressDialog有模态和非模态两种使用方式,支持自定义标签文本和取消按钮。当进度达到最大值或用户取消时,可以自动重置和关闭。示例代码展示了如何结合定时器使用QProgressDialog来模拟任务进度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进度对话框QProgressDialog

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设置进度条的当前值
valueint获取进度条的当前值
[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()设置显示的文本。

fusion-progressdialog.png

进度对话框QProgressDialog 的信号

进度对话框 QProgressDialog 只有一个信号 canceled(),单击对话中的 Cancel 按时发送信号。

进度对话框QProgressDialog 的应用实例

下面的程序将进度对话框和定时器相结合,定时器每隔 200 毫秒发送一个信息。进度条的值随时间的推移逐渐增大,当超过进度条的最大值或单击 Cancel 按钮后,进度条被隐藏和重置。

image-20230218203332772

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())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

士别三日,当挖目相待

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值