进度条类控件主要显示任务的执行进度,PyQt5中提供了进度条控件和滑块控件这两种类型的进度条类控件。其中,进度条控件是通常所看到的进度条,用ProgressBar控件表示;而滑块控件是以刻度线的形式出现。本节将对PyQt5中的进度条类控件进行详细讲解。
1 ProgressBar:进度条
ProgressBar控件表示进度条,通常在执行长时间任务时,用进度条告诉用户当前的进展情况。
ProgressBar控件对应PyQt5中的QProgressBar类,它其实就是QProgressBar类的一个对象。QProgressBar类的常用方法及说明如表所示。
| 方 法 | 说 明 |
|---|---|
| setMinimum() | 设置进度条的最小值,默认值为0 |
| setMaximum() | 设置进度条的最大值,默认值为99 |
| setRange() | 设置进度条的取值范围,相当于setMinimum()和setMaximum()方法的结合 |
| setValue() | 设置进度条的当前值 |
| setFormat() | 设置进度条的文字显示格式,有以下3种格式: ◆ %p%:显示完成的百分比,默认格式 ◆ %v:显示当前的进度值 ◆ %m:显示总的步长值 |
| setAlignment() | 设置对齐方式,有水平和垂直两种,分别如下: ◆ 水平对齐方式: ■ Qt.AlignLeft:左对齐 ■ Qt.AlignHCenter:水平居中对齐 ■ Qt.AlignRight:右对齐 ■ Qt.AlignJustify:两端对齐 ◆ 垂直对齐方式: ■ Qt.AlignTop:顶部对齐 ■ Qt.AlignVCenter:垂直居中 ■ Qt.AlignBottom:底部对齐 |
| setLayoutDirection() | 设置进度条的布局方向,支持以下3个方向值: ◆ Qt.LeftToRight:从左至右 ◆ Qt.RightToLeft:从右至左 ◆ Qt.LayoutDirectionAuto:跟随布局方向自动调整 |
| setOrientation() | 设置进度条的显示方向,有以下两个方向: ◆ Qt.Horizontal:水平方向 ◆ Qt.Vertical:垂直方向 |
| setInvertedAppearance() | 设置进度条是否以反方向显示进度 |
| setTextDirection() | 设置进度条的文本显示方向,有以下两个方向: ◆ QProgressBar.TopToBottom:从上到下 ◆ QProgressBar.BottomToTop:从下到上 |
| setProperty() | 对进度条的属性进行设置,可以是任何属性,比如,self.progressBar.setProperty("value", 24) |
| minimum() | 获取进度条的最小值 |
| maximum() | 获取进度条的最大值 |
| value() | 获取进度条的当前值 |
ProgressBar控件中最常用的信号是valueChanged,在进度条的值发生改变时发射。
通过对ProgressBar控件的显示方向、对齐方式、布局方向等进行设置,该控件可以支持4种水平进度条显示方式和两种垂直进度条显示方式,它们的效果如图所示,用户可以根据自身需要选择适合自己的显示方式。

Tip: 多学两招 如果最小值和最大值都设置为
0,那么进度条会显示为一个不断循环滚动的繁忙进度,而不是步骤中显示的百分比。
实例 模拟一个跑马灯效果
打开Qt Designer设计器,创建一个窗口,并向窗口中添加4个ProgressBar控件和一个PushButton控件,然后将该窗口转换为.py文件,在.py文件中对进度条和PushButton按钮的clicked信号进行绑定,代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(305, 259)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.progressBar = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar.setGeometry(QtCore.QRect(50, 10, 201, 31))
self.progressBar.setLayoutDirection(QtCore.Qt.LeftToRight)
self.progressBar.setProperty("value", -1)
self.progressBar.setAlignment(QtCore.Qt.AlignHCenter|QtCore.Qt.AlignTop)
self.progressBar.setTextVisible(True)
self.progressBar.setOrientation(QtCore.Qt.Horizontal)
self.progressBar.setTextDirection(QtWidgets.QProgressBar.TopToBottom)
self.progressBar.setFormat("")
self.progressBar.setObjectName("progressBar")
self.progressBar_2 = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar_2.setGeometry(QtCore.QRect(50, 180, 201, 31))
self.progressBar_2.setLayoutDirection(QtCore.Qt.RightToLeft)
self.progressBar_2.setProperty("value", -1)
self.progressBar_2.setAlignment(QtCore.Qt.AlignBottom|QtCore.Qt.AlignHCenter)
self.progressBar_2.setTextVisible(True)
self.progressBar_2.setOrientation(QtCore.Qt.Horizontal)
self.progressBar_2.setTextDirection(QtWidgets.QProgressBar.TopToBottom)
self.progressBar_2.setObjectName("progressBar_2")
self.progressBar_3 = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar_3.setGeometry(QtCore.QRect(20, 10, 31, 201))
self.progressBar_3.setLayoutDirection(QtCore.Qt.LeftToRight)
self.progressBar_3.setProperty("value", -1)
self.progressBar_3.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.progressBar_3.setTextVisible(True)
self.progressBar_3.setOrientation(QtCore.Qt.Vertical)
self.progressBar_3.setTextDirection(QtWidgets.QProgressBar.TopToBottom)
self.progressBar_3.setObjectName("progressBar_3")
self.progressBar_1 = QtWidgets.QProgressBar(self.centralwidget)
self.progressBar_1.setGeometry(QtCore.QRect(250, 10, 31, 201))
self.progressBar_1.setLayoutDirection(QtCore.Qt.LeftToRight)
self.progressBar_1.setProperty("value", -1)
self.progressBar_1.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.progressBar_1.setTextVisible(True)
self.progressBar_1.setOrientation(QtCore.Qt.Vertical)
self.progressBar_1.setTextDirection(QtWidgets.QProgressBar.TopToBottom)
self.progressBar_1.setObjectName("progressBar_1")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(90, 220, 101, 31))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.timer = QtCore.QBasicTimer() # 创建计时器对象
# 为按钮绑定单击信号
self.pushButton.clicked.connect(self.running)
# 控制进度条的滚动效果
def running(self):
if self.timer.isActive(): # 判断计时器是否开启
self.timer.stop() # 停止计时器
self.pushButton.setText('开始') # 设置按钮的文本
# 设置4个进度条的最大值为100
self.progressBar.setMaximum(100)
self.progressBar_1.setMaximum(100)
self.progressBar_2.setMaximum(100)
self.progressBar_3.setMaximum(100)
else:
self.timer.start(100,MainWindow) # 启动计时器
self.pushButton.setText('停止') # 设置按钮的文本
# 将4个进度条的最大值和最小值都设置为0,以便显示循环滚动的效果
self.progressBar.setMinimum(0)
self.progressBar.setMaximum(0)
self.progressBar_1.setInvertedAppearance(True) # 设置进度反方向显示
self.progressBar_1.setMinimum(0)
self.progressBar_1.setMaximum(0)
self.progressBar_2.setMinimum(0)
self.progressBar_2.setMaximum(0)
self.progressBar_3.setMinimum(0)
self.progressBar_3.setMaximum(0)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "跑马灯效果"))
self.pushButton.setText(_translate("MainWindow", "开始"))
import sys
# 程序入口,程序从此处启动PyQt设计的窗体
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow() # 创建窗体对象
ui = Ui_MainWindow() # 创建PyQt设计的窗体对象
ui.setupUi(MainWindow) # 调用PyQt窗体的方法对窗体对象进行初始化设置
MainWindow.show() # 显示窗体
sys.exit(app.exec_()) # 程序关闭时退出进程
Tip: 多学两招 上面代码中用到了
QBasicTimer类,该类是QtCore模块中包含的一个类,主要用来为对象提供定时器事件。QBasicTimer定时器是一个重复的定时器,除非调用stop()方法,否则它将发送后续的定时器事件。启动定时器使用start()方法,该方法有两个参数,分别为超时时间(毫秒)和接收事件的对象;而停止定时器时使用stop()方法即可。
运行程序,初始效果如图所示;

单击开始按钮,启动跑马灯效果,并且按钮的文本变为停止,如图所示,单击停止按钮,即可恢复如上图所示的默认效果。

2 自定义等待提示框
在使用PyQt5创建桌面窗口应用程序时,有时会遇到等待长任务执行的情况,PyQt5中提供的ProgressBar控件(即QProgressBar对象)虽然也可以通过循环滚动的方式等待任务执行完成,但与通常见到的类似图所示的等待提示框相比,在美观程度上有所欠缺,因此本节将介绍如何在PyQt5中自定义等待提示。

实例 设置自定义等待提示框
使用PyQt5实现等待提示框时,可以通过加载GIF图片的方式模拟等待提示框,首先在创建主窗口时,在窗口的中间位置添加一个可以加载GIF图片的Label控件,然后再添加两个PushButton按钮,分别用于控制等待提示框的启动与停止。代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(682, 583)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# 创建主布局
self.main_layout = QtWidgets.QVBoxLayout(self.centralwidget)
self.loading = QtWidgets.QLabel(self.centralwidget)
self.loading.setStyleSheet("")
self.loading.setText("")
self.loading.setObjectName("loading")
# 设置GIF居中显示
self.loading.setAlignment(QtCore.Qt.AlignCenter)
# 添加到布局
self.main_layout.addWidget(self.loading)
# 创建按钮布局
self.button_layout = QtWidgets.QHBoxLayout()
self.pushButton_start = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_start.setMinimumSize(QtCore.QSize(100, 50))
self.pushButton_start.setObjectName("pushButton_start")
self.button_layout.addWidget(self.pushButton_start)
# 添加伸缩项,让两个按钮分开
self.button_layout.addStretch()
self.pushButton_stop = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_stop.setMinimumSize(QtCore.QSize(100, 50))
self.pushButton_stop.setObjectName("pushButton_stop")
self.button_layout.addWidget(self.pushButton_stop)
# 将按钮布局添加到主布局
self.main_layout.addLayout(self.button_layout)
# 设置按钮区域的最小高度
self.main_layout.setStretch(0, 3) # GIF区域占3份高度
self.main_layout.setStretch(1, 1) # 按钮区域占1份高度
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
self.pushButton_start.clicked.connect(self.start_loading)
self.pushButton_stop.clicked.connect(self.stop_loading)
def start_loading(self):
self.gif = QtGui.QMovie('loading.gif')
# 设置GIF缩放模式,保持比例适应标签大小
self.loading.setScaledContents(True)
self.loading.setMovie(self.gif)
self.gif.start()
def stop_loading(self):
if hasattr(self, 'gif'): # 避免未启动时点击停止报错
self.gif.stop()
self.loading.clear()
self.loading.setScaledContents(False) # 恢复默认状态
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "加载动画演示"))
self.pushButton_start.setText(_translate("MainWindow", "启动等待提示"))
self.pushButton_stop.setText(_translate("MainWindow", "停止等待提示"))
import sys
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Info: 说明 上面代码中使用
QLabel类的setMovie()方法为其设置要显示的GIF动画图片,该方法要求有一个QMovie对象作为参数,QMovie类是QtGui模块中提供的一个用来显示简单且没有声音动画的类。
运行程序,单击启动等待提示按钮,将显示如图所示的运行效果;单击停止等待提示按钮,将自动关闭等待提示框。
3 滑块:QSlider
PyQt5中提供了两个滑块控件,分别是水平滑块HorizontalSlider和垂直滑块VerticalSlider,但这两个滑块控件对应的类都是QSlider类,该类中提供了一个setOrientation()方法,通过设置该方法的参数,可以将滑块显示为水平或者垂直。
QSlider滑块类的常用方法及说明如表所示。
| 方 法 | 说 明 |
|---|---|
| setMinimum() | 设置滑块最小值 |
| setMaximum() | 设置滑块最大值 |
| setOrientation() | 设置滑块显示方向,取值如下: ◆ Qt.Horizontal:水平滑块 ◆ Qt.Vertical:垂直滑块 |
| setPageStep() | 设置步长值,通过鼠标点击滑块时使用 |
| setSingleStep() | 设置步长值,通过鼠标拖动滑块时使用 |
| setValue() | 设置滑块的值 |
| setTickInterval() | 设置滑块的刻度间隔 |
| setTickPosition() | 设置滑块刻度的标记位置,取值如下: ◆ QSlider.NoTicks:不显示刻度,这是默认设置 ◆ QSlider.TicksBothSides:在滑块的两侧都显示刻度 ◆ QSlider.TicksAbove:在水平滑块的上方显示刻度 ◆ QSlider.TicksBelow:在水平滑块的下方显示刻度 ◆ QSlider.TicksLeft:在垂直滑块的左侧显示刻度 ◆ QSlider.TicksRight:在垂直滑块的右侧显示刻度 |
| value() | 获取滑块的当前值 |
QSlider滑块类的常用信号及说明如表所示。
| 信 号 | 说 明 |
|---|---|
| valueChanged | 当滑块的值发生改变时发射该信号 |
| sliderPressed | 当用户按下滑块时发射该信号 |
| sliderMoved | 当用户拖动滑块时发射该信号 |
| sliderReleased | 当用户释放滑块时发射该信号 |
Warning: 注意
QSlider滑块只能控制整数范围,因此它不适用于需要准确的大范围取值的场景。
实例 使用滑块改变刻度值及标签中的字体大小
在Qt Designer设计器中创建一个窗口,在窗口中分别添加一个HorizontalSlider水平滑块和一个VerticalSlider垂直滑块,然后添加一个HorizontalLayout水平布局管理器,在该布局管理器中添加一个Label标签,用来显示文字。设计完成后,保存为.ui文件,并使用Pyuic工具将其转换为.py代码文件。在.py文件中通过绑定水平滑块的valueChanged信号,实现拖动水平滑块时,实时改变垂直滑块的刻度值,同时改变Label标签中的字体大小。代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(313, 196)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# 创建水平滑块
self.horizontalSlider = QtWidgets.QSlider(self.centralwidget)
self.horizontalSlider.setGeometry(QtCore.QRect(20, 10, 231, 22))
self.horizontalSlider.setMinimum(8) # 设置最小值为8
self.horizontalSlider.setMaximum(72) # 设置最大值为72
self.horizontalSlider.setSingleStep(1) # 设置通过鼠标拖动时的步长值
self.horizontalSlider.setPageStep(1) # 设置通过鼠标点击时的步长值
self.horizontalSlider.setProperty("value", 8) # 设置默认值为8
self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal) # 设置滑块为水平滑块
# 设置在滑块上方显示刻度
self.horizontalSlider.setTickPosition(QtWidgets.QSlider.TicksAbove)
self.horizontalSlider.setTickInterval(3) # 设置刻度的间隔
self.horizontalSlider.setObjectName("horizontalSlider")
# 创建垂直滑块
self.verticalSlider = QtWidgets.QSlider(self.centralwidget)
self.verticalSlider.setGeometry(QtCore.QRect(270, 20, 22, 171))
self.verticalSlider.setMinimum(8) # 设置最小值为8
self.verticalSlider.setMaximum(72) # 设置最大值为72
self.verticalSlider.setOrientation(QtCore.Qt.Vertical) # 设置滑块为垂直滑块
self.verticalSlider.setInvertedAppearance(True) # 设置刻度反方向显示
# 设置在滑块右侧显示刻度
self.verticalSlider.setTickPosition(QtWidgets.QSlider.TicksRight)
self.verticalSlider.setTickInterval(3) # 设置刻度的间隔
self.verticalSlider.setObjectName("verticalSlider")
# 创建一个水平布局管理器,主要用来放置显示文字的Label
self.horizontalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(20, 70, 251, 80))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
# 创建Label控件,用来显示文字
self.label = QtWidgets.QLabel(self.horizontalLayoutWidget)
self.label.setAlignment(QtCore.Qt.AlignCenter) # 设置文字居中对齐
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label) # 将Label添加到水平布局管理器中
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
# 为水平滑块绑定valueChanged信号,在值发生更改时发射
self.horizontalSlider.valueChanged.connect(self.setfontsize)
# 定义槽函数,根据水平滑块的值改变垂直滑块的值和Label控件的字体大小
def setfontsize(self):
value = self.horizontalSlider.value()
self.verticalSlider.setValue(value)
self.label.setFont(QtGui.QFont("楷体", value))
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "敢想敢为,注重细节"))
import sys
# 程序入口,程序从此处启动PyQt设计的窗体
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow() # 创建窗体对象
ui = Ui_MainWindow() # 创建PyQt设计的窗体对象
ui.setupUi(MainWindow) # 调用PyQt窗体的方法对窗体对象进行初始化设置
MainWindow.show() # 显示窗体
sys.exit(app.exec_()) # 程序关闭时退出进程
Info: 说明 上面代码中用到了水平布局管理器
HorizontalLayout,它实质上是一个QHBoxLayout类的对象,它在这里的主要作用是放置Label控件,这样Label控件就只可以在水平布局管理器中显示,避免字体设置过大时,超出窗口范围的问题。
运行程序,默认效果如图所示,当用鼠标拖动水平滑块的刻度时,垂直滑块的刻度值会随之变化。另外,Label标签中的文字大小也会发生改变,如图所示。
- 默认效果

- 拖动水平滑块改变垂直滑块和字体大小
