(四)PyQt5高级控件的使用
PyQt5中包含了很多用于简化窗口设计的可视化控件,除了常用控件外,还有一些关于进度、展示数据等的高级控件。
本章重点讲解PyQt5程序开发中用到的一些高级控件,主要包括ProgressBar进度条控件、QSlider滑块控件、树控件、分割线控件、弹簧控件、Dial旋钮控件和QScrollBar滚动条控件,另外,还对如何在程序中自定义等待提示框进行了介绍。学习本章内容时,重点需要掌握ProgressBar进度条控件、QSlider滑块控件和TreeWidget树控件的使用方法。
1. 进度条类控件
进度条类控件主要显示任务的执行进度,PyQt5提供了进度条控件和滑块控件这两种类型的进度条控件。其中,进度条控件是我们通常所看到的进度条,用ProgressBar控件表示,而滑块控件是以刻度线的形式出现。
1. ProgressBar:进度条
ProgressBar控件表示进度条,通常在执行长时间任务时,用进度条告诉用户当前的进展情况。
ProgressBar控件对应PyQt5中的QProgressBar类,它其实就是QProgressBar类的一个对象。
QProgressBar类的常用方法及说明
方法 | 说明 |
setMinimun() | 设置进度条的最小值,默认值为0。 |
setMaximun() | 设置进度条的最大值,默认值为99。 |
setRange() | 设置进度条的取值范围,相当于setMinimum()和settMaximum()的结合。 |
setValue() | 设置进度条的当前值。 |
setFormat() |
|
setLayoutDirection() |
|
setAlignment() | 设置对齐方式,有水平和垂直两种,分别如下:
|
setOrientation() |
|
setInvertedAppearance() | 设置进度条是否以反方向显示进度。 |
setTextDirection() |
|
setProperty() | 对进度条的属性进行设置,可以是任何属性,如self.progressBar.setProperty("value", 24)。 |
minimum() | 获取进度条的最小值。 |
maximum() | 获取进度条的最大值。 |
value() | 获取进度条的当前值。 |
ProgressBar控件最常用的信号是valueChanged,在进度条的值发生改变时发射。
通过对ProgressBar控件的显示方向、对齐方式、布局方向等进行设置,该控件可以支持4种水平进度条显示方式和2种垂直进度条显示方式,用户可以根据自身需要选择适合自己的显示方式。
如果将最小值和最大值都设置为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.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_())
运行效果如下:
QBasicTimer类的简单介绍
上面代码用到了QBasicTimer类,该类是QtCore模块中包含的一个类,主要用来为对象提供定时器事件。QBasicTimer定时器是一个重复的定时器,除非调用stop()方法,否则它将发送后续的定时器事件。启动定时器使用start()方法,该方法有两个参数,分别为超时时间(毫秒)和接收事件的对象,而停止定时器使用stop()方法即可。
2. 自定义等待提示框
在使用PyQt5创建桌面窗口应用程序时,有时会遇到等待长任务执行的情况,PyQt5提供的ProgressBar控件(即QProgressBar对象)虽然也可以通过循环滚动的方式等待任务执行完成,但与我们通常见到的下图所示的等待提示框相比,不是特别美观。
示例:自定义等待提示框
使用PyQt5实现等待提示框时,可以通过加载gif图片的方式模拟等待提示框,首先在创建主窗口时,在窗口的中间位置添加一个可以加载gif图片的Label控件,然后再添加两个PushButton按钮,分别用于控制等待提示框的启动与停止。
完整代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
# MainWindow.resize(400, 227)
MainWindow.resize(300, 300)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.loading = QtWidgets.QLabel(self.centralwidget)
# self.loading.setGeometry(QtCore.QRect(150, 20, 100, 100))
self.loading.setGeometry(QtCore.QRect(70, 20, 200, 200))
self.loading.setStyleSheet("")
self.loading.setText("")
self.loading.setObjectName("loading")
self.pushButton_start = QtWidgets.QPushButton(self.centralwidget)
# self.pushButton_start.setGeometry(QtCore.QRect(50, 140, 100, 50))
self.pushButton_start.setGeometry(QtCore.QRect(20, 230, 100, 50))
self.pushButton_start.setObjectName("pushButton_start")
self.pushButton_stop = QtWidgets.QPushButton(self.centralwidget)
# self.pushButton_stop.setGeometry(QtCore.QRect(250, 140, 100, 50))
self.pushButton_stop.setGeometry(QtCore.QRect(180, 230, 100, 50))
self.pushButton_stop.setObjectName("pushButton_stop")
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("./image/loading.gif") # 加载gif图片
self.loading.setMovie(self.gif) # 设置gif图片
self.gif.start() # 启动图片,实现等待gif图片的显示
def stop_loading(self):
self.gif.stop()
self.loading.clear()
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton_start.setText(_translate("MainWindow", "启动等待提示"))
self.pushButton_stop.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_()) # 程序关闭时退出程序
运行结果如图所示:
使用的动态图如下:
上面代码中使用QLabel类的setMovie()方法为其设置要显示的gif动画图片,该方法要求有一个QMovie对象作为参数,QMovie类是QtGui模块中提供的一个用来显示简单且没有声音动画的类。
3. 滑块:QSlider
PyQt5提供了两个滑块控件,分别是水平滑块HorizontalSlider和垂直滑块VerticalSlider,但这两个滑块控件对应的类都是QSlider类,该类提供了一个setOrientation()方法,通过设置该方法的参数,可以将滑块显示为水平或者垂直。
QSlider滑块类的常用方法及说明
<tr>
<td>setTickPosition()</td>
<td>
<ul align="left">设置滑块刻度的标记位置,取值如下:
<li>QSlider.NoTicks:不显示刻度,这是默认设置;</li>
<li>QSlider.TicksBothSides:在滑块的两侧都显示刻度;</li>
<li>QSlider.TicksAbove:在水平滑块的上方显示刻度;</li>
<li>QSlider.TicksBelow:在水平滑块的下方显示刻度;</li>
<li>QSlider.TicksLeft:在垂直滑块的左侧显示刻度;</li>
<li>QSlider.TicksRight:在垂直滑块的右侧显示刻度。</li>
</ul>
</td>
</tr>
<tr>
<td>value()</td>
<td>获取滑块的当前值。</td>
</tr>
方法 | 说明 |
setMinumum() | 设置滑块最小值。 |
setMaximum()> | 设置滑块最大值。 |
setOrientation() |
|
setPageStep() | 设置步长值,通过鼠标**点击滑块时**使用。 |
setSingleStep() | 设置步长值,通过鼠标**拖动滑块时**使用。 |
setValue() | 设置滑块的值。 |
setTickInterval() | 设置滑块的刻度间隔。 |
QSlider滑块类的常用信号及说明
信号 | 说明 |
valueChanged | 当滑块的值发生改变时发射信号。 |
sliderPressed | 当用户按下滑块时发射该信号。 |
sliderMoved | 当用户拖动滑块时发射该信号。 |
sliderReleased | 当用户释放滑块时发射该信号。 |
注意,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) # 设置滑块为垂直滑块
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.setGeometry(QtCore.QRect(20, 70, 251, 80))
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", "MainWidnow"))
self.label.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_())
说明:上面代码用到了水平布局管理器HorizontalLayout,它实质上是一个QHBoxLayout类的对象,它在这里的主要作用是放置Label控件,这样,Label控件就只可以在水平布局管理器中显示,避免了字体设置过大时,超出窗口范围的问题。
运行程序,当鼠标拖动水平滑块的刻度时,垂直滑块的刻度值会随之变化,另外。Label标签中的文字也会发生改变:
2. 树控件
树控件可以为用户显示节点层次结构,而每个节点又可以包含子节点,包含子节点的节点叫父节点,在设计树形结构(如导航菜单等)时,很方便。PyQt5提供了两个树控件,分别是TreeView和TreeWidget。
1. TreeView:树视图
TreeView控件对应PyQt5的QTreeView类,它是树控件的基类,使用时,必须为其提供一个模型来与之配合。
QTreeView类的常用方法及说明
方法 | 说明 |
autoExpandDelay() | 获取自动展开节点所需要的延迟时间。 |
collapse() | 收缩指定级的节点。 |
collapseAll() | 收缩所有节点。 |
expand() | 展开指定级的节点。 |
expandAll() | 展开所有节点。 |
header() | 树的头信息,常用的有一个setVisible()方法,用来设置是否显示头。 |
isHeaderHidder() | 判断是都隐藏头部。 |
setAutoExpandDelay() | 设置自动展开的延时时间,单位为毫秒,如果值小于0,表示禁用自动展开。 |
setAlternatingRowColors() | 设置每间隔一行颜色是否一样。 |
setExpanded() | 根据索引设置是否展开节点。 |
setHeaderHidden() | 设置是否隐藏头部。 |
setItemsExpandable() | 设置项是否展开。 |
setMode() | 设置要显示的数据模型。 |
setSortingEnabled() | 设置单击头部是否可以排序。 |
setVerticalScrollBarPolicy() | 设置是否显示垂直滚动条。 |
setHorizontalScrollBarPolicy() | 设置是否显示水平滚动条。 |
setEditTriggers() | 设置默认的编辑触发器。 |
setExpandsOnDoubleClick() | 设置是否支持双击展开树节点。 |
setWordWrap() | 设置自动换行。 |
selectionModel() | 获取选中的模型。 |
sortByColumn() | 根据列排序。 |
setSelectionMode() |
|
setSelectionBehavior() |
|
使用TreeView控件分层显示PyQt5内置模型的数据和自定义的数据。
1. 使用内置模型中的数据
PyQt5提供的内置模型及说明
模型 | 说明 |
QStringListModel | 存储简单的字符串列表。 |
QStandardItemModel | 可以用于树结构的存储,提供了层次数据。 |
QFileSystemModel | 存储本地系统的文件和目录信息(针对当前项目) |
QDirModel | 存储文件系统。 |
QsqlQueryModel | 存储SQL的查询结构集。 |
QsqlTableModel | 存储SQL中的表格数据。 |
QsqlRelationalTableModel | 存储有外键关系的SQL表格数据。 |
QSortFilterProxyModel | 对模型中的数据进行排序或者过滤。 |
示例:显示系统文件目录
使用系统内置的QDirModel作为数据模型,在TreeView中显示系统的文件目录。
完整代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 400)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.treeView = QtWidgets.QTreeView(self.centralwidget) # 创建树对象
self.treeView.setGeometry(QtCore.QRect(0, 0, 794, 395)) # 设置坐标位置和大小
# 设置垂直滚动条为按需显示
self.treeView.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
# 设置水平滚动条为按需显示
self.treeView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
# 设置双击或者按下Enter键时,树节点可编辑
self.treeView.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked | QtWidgets.QAbstractItemView.EditKeyPressed)
# 设置树节点为单选
self.treeView.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
# 设置选中节点时为整行选中
self.treeView.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.treeView.setAutoExpandDelay(-1) # 设置自动展开延时为-1,表示自动展开不可用
self.treeView.setItemsExpandable(True) # 设置是否可以展开项
self.treeView.setSortingEnabled(True) # 设置单击头部可排序
self.treeView.setWordWrap(True) # 设置自动换行
self.treeView.setHeaderHidden(False) # 设置不隐藏头部
self.treeView.setExpandsOnDoubleClick(True) # 设置双击可以展开节点
self.treeView.setObjectName("treeView")
self.treeView.header().setVisible(True) # 设置显示头部
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
model = QtWidgets.QDirModel() # 创建存储文件系统的模型
self.treeView.setModel(model) # 为树控件设置数据模型
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWidow"))
import sys
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_())
运行效果如图所示:
2. 使用自定义数据
PyQt5提供了一个QStandardItemModel模型,该模型可以存储任意层次结构的数据。下面介绍如何使用QStandardItemModel模型存储数据结构,并显示在TreeView控件中。
示例:使用TreeView显示各班级的学生成绩信息
创建一个PyQt窗口,并在其中添加一个TreeView控件,然后在.py文件中使用QStandardItemModel模型存储某年级下的各个班级的学生成绩信息,最后将设置完的QStandardItemModel模型作为TreeView控件的数据模型进行显示。
完整代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(600, 900)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# 创建一个TreeView树视图
self.treeView = QtWidgets.QTreeView(self.centralwidget)
self.treeView.setGeometry(QtCore.QRect(0, 0, 599, 898))
self.treeView.setObjectName("treeView")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
model = QtGui.QStandardItemModel() # 创建数据模型
model.setHorizontalHeaderLabels(["年级", "班级", "姓名", "分数"])
name = ["橘真琴", "远坂凛", "雾影才藏", "猿飞佐助", "真田幸村", "伊佐那海", "龙之峰帝人", "平和岛静雄", "结城新十郎", "漩涡鸣人", "夜刀神狗郎", "伊佐那社"] # 姓名列表
score = [90, 80, 80, 80, 87, 89, 87, 88, 78, 89, 89, 94] # 分数列表
import random
# 设置数据
for i in range(0, 6):
# 一级节点:年级,只设第1列的数据
grade = QtGui.QStandardItem(("%s 年级") % (i + 1))
model.appendRow(grade) # 一级节点
for j in range(0, 4):
# 二级节点:班级、姓名、分数
itemClass = QtGui.QStandardItem(("%s 班") % (j + 1))
itemName = QtGui.QStandardItem(name[random.randrange(10)])
itemScore = QtGui.QStandardItem(str(score[random.randrange(10)]))
# 将二级节点添加到一级节点上
grade.appendRow([QtGui.QStandardItem(""), itemClass, itemName, itemScore])
self.treeView.setModel(model) # 为TreeView设置数据模型
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
import sys
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_()) # 程序关闭时退出进程
运行程序,可以展开年级节点:
2. TreeWidget:树控件
TreeWidget控件对应于PyQt5中的QTreeWidget类,它提供了一个使用预定义树模型的树视图,它的每一个树节点都是一个QTreeWidgetItem。
QTreeWidget类的常用方法及说明
方法 | 说明 |
addTopLevelItem() | 添加顶级节点 |
insertTopLevelItems() | 在树的顶层索引中插入节点 |
invisibleRootItem() | 获取树控件中不可见的根选项 |
setColumnCount() | 设置要显示的列数 |
setColumnWidth() | 设置列的宽度 |
selectedItems() | 获取选中的树节点 |
QTreeWidgetItem中的树节点项。 |
QTreeWidgetItem类的常用方法及说明
方法 | 说明 |
addChild() | 添加子节点。 |
setText() | 设置节点的文本。 |
setCheckState() |
|
setIcon() | 为节点设置图标。 |
text() | 获取节点的文本。 |
TreeWidget控件的常见用法如下:
1. 使用TreeWidget控件显示树结构
使用TreeWidget控件显示树结构主要用到QTreeWidgetItem类,该类表示标准树节点,通过其setText()方法可以设置树节点的文本。
示例:使用TreeWidget显示树结构
创建一个PyQt5窗口,并在其中添加一个TreeWidget控件,然后保存为.ui文件,并使用PyUIC工具将其转换为.py文件,在.py文件中,通过创建QTreeWidgetItem对象为树控件设置树节点。
完整代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QTreeWidgetItem
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(400, 300)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.treeWidget = QtWidgets.QTreeWidget(self.centralwidget)
self.treeWidget.setGeometry(QtCore.QRect(0, 0, 400, 300))
self.treeWidget.setObjectName("treeWidget")
self.treeWidget.setColumnCount(2) # 设置树结构中的列数
self.treeWidget.setHeaderLabels(["姓名", "职务"]) # 设置列标题名
root = QTreeWidgetItem(self.treeWidget) # 创建节点
root.setText(0, "组织结构") # 设置顶级节点文本
# 定义字典,存储树中显示的数据
dict = {"任正非": "华为董事长", "马云": "阿里巴巴创始人", "马化腾": "腾讯 CEO", "李彦宏": "百度 CEO", "董明珠": "格力董事长"}
for key, value in dict.items(): # 遍历字典
child = QTreeWidgetItem(root) # 创建子节点
child.setText(0, key) # 设置第一列的值
child.setText(1, value) # 设置第二列的值
self.treeWidget.addTopLevelItem(root) # 将创建的树节点添加到树控件中
self.treeWidget.expandAll() # 展开所有节点
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "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_())
运行结果如图所示:
2. 为节点设置图标
为节点设置图标主要用到了QtWidgetItem类的setIcon()方法。
示例:为前一个示例中第一列的每个企业家姓名前面设置其对应公司的图标
关键代码如下:
# 为节点设置图标
if key == "任正非":
child.setIcon(0, QtGui.QIcon("image/华为.png"))
elif key == "马云":
child.setIcon(0, QtGui.QIcon("image/阿里巴巴.png"))
elif key == "马化腾":
child.setIcon(0, QtGui.QIcon("image/腾讯.png"))
elif key == "李彦宏":
child.setIcon(0, QtGui.QIcon("image/百度.png"))
elif key == "董明珠":
child.setIcon(0, QtGui.QIcon("image/格力.png"))
完整代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QTreeWidgetItem
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(400, 300)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.treeWidget = QtWidgets.QTreeWidget(self.centralwidget)
self.treeWidget.setGeometry(QtCore.QRect(0, 0, 400, 300))
self.treeWidget.setObjectName("treeWidget")
self.treeWidget.setColumnCount(2) # 设置树结构中的列数
self.treeWidget.setHeaderLabels(["姓名", "职务"]) # 设置列标题名
root = QTreeWidgetItem(self.treeWidget) # 创建节点
root.setText(0, "组织结构") # 设置顶级节点文本
# 定义字典,存储树中显示的数据
dict = {"任正非": "华为董事长", "马云": "阿里巴巴创始人", "马化腾": "腾讯 CEO", "李彦宏": "百度 CEO", "董明珠": "格力董事长"}
for key, value in dict.items(): # 遍历字典
child = QTreeWidgetItem(root) # 创建子节点
child.setText(0, key) # 设置第一列的值
child.setText(1, value) # 设置第二列的值
# 为节点设置图标
if key == "任正非":
child.setIcon(0, QtGui.QIcon("image/华为.png"))
elif key == "马云":
child.setIcon(0, QtGui.QIcon("image/阿里巴巴.png"))
elif key == "马化腾":
child.setIcon(0, QtGui.QIcon("image/腾讯.png"))
elif key == "李彦宏":
child.setIcon(0, QtGui.QIcon("image/百度.png"))
elif key == "董明珠":
child.setIcon(0, QtGui.QIcon("image/格力.png"))
self.treeWidget.addTopLevelItem(root) # 将创建的树节点添加到树控件中
self.treeWidget.expandAll() # 展开所有节点
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "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_())
运行结果:
3. 为节点设置复选框
为节点设置复选框主要用到了QTreeWidgetItem类的setCheckState()方法,该方法可以设置选中(Qt.Checked),也可以设置未选中(Qt.Unchecked)。
示例:为上一示例中的第一列设置复选框,并全部设置为选中状态。
关键代码:
child.setCheckState(0, QtCore.Qt.Checked) # 为节点设置复选框,并且选中
全部代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QTreeWidgetItem
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(400, 300)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.treeWidget = QtWidgets.QTreeWidget(self.centralwidget)
self.treeWidget.setGeometry(QtCore.QRect(0, 0, 400, 300))
self.treeWidget.setObjectName("treeWidget")
self.treeWidget.setColumnCount(2) # 设置树结构中的列数
self.treeWidget.setHeaderLabels(["姓名", "职务"]) # 设置列标题名
root = QTreeWidgetItem(self.treeWidget) # 创建节点
root.setText(0, "组织结构") # 设置顶级节点文本
# 定义字典,存储树中显示的数据
dict = {"任正非": "华为董事长", "马云": "阿里巴巴创始人", "马化腾": "腾讯 CEO", "李彦宏": "百度 CEO", "董明珠": "格力董事长"}
for key, value in dict.items(): # 遍历字典
child = QTreeWidgetItem(root) # 创建子节点
child.setText(0, key) # 设置第一列的值
child.setText(1, value) # 设置第二列的值
# 为节点设置图标
if key == "任正非":
child.setIcon(0, QtGui.QIcon("image/华为.png"))
elif key == "马云":
child.setIcon(0, QtGui.QIcon("image/阿里巴巴.png"))
elif key == "马化腾":
child.setIcon(0, QtGui.QIcon("image/腾讯.png"))
elif key == "李彦宏":
child.setIcon(0, QtGui.QIcon("image/百度.png"))
elif key == "董明珠":
child.setIcon(0, QtGui.QIcon("image/格力.png"))
child.setCheckState(0, QtCore.Qt.Checked) # 为节点设置复选框,并且选中
self.treeWidget.addTopLevelItem(root) # 将创建的树节点添加到树控件中
self.treeWidget.expandAll() # 展开所有节点
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "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_())
运行效果:
4. 设置各行变色显示树节点
隔行变色显示树节点需要用到TreeWidget控件的setAlternatingRowColors()方法,设置为True表示隔行换色,设置为False表示统一颜色。
示例:将上一示例中的树设置为隔行变色形式显示
关键代码如下:
# 设置隔行变色
self.treeWidget.setAlternatingRowColors(True)
完整代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QTreeWidgetItem
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(400, 300)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.treeWidget = QtWidgets.QTreeWidget(self.centralwidget)
self.treeWidget.setGeometry(QtCore.QRect(0, 0, 400, 300))
self.treeWidget.setObjectName("treeWidget")
self.treeWidget.setColumnCount(2) # 设置树结构中的列数
self.treeWidget.setHeaderLabels(["姓名", "职务"]) # 设置列标题名
# 设置隔行变色
self.treeWidget.setAlternatingRowColors(True)
root = QTreeWidgetItem(self.treeWidget) # 创建节点
root.setText(0, "组织结构") # 设置顶级节点文本
# 定义字典,存储树中显示的数据
dict = {"任正非": "华为董事长", "马云": "阿里巴巴创始人", "马化腾": "腾讯 CEO", "李彦宏": "百度 CEO", "董明珠": "格力董事长"}
for key, value in dict.items(): # 遍历字典
child = QTreeWidgetItem(root) # 创建子节点
child.setText(0, key) # 设置第一列的值
child.setText(1, value) # 设置第二列的值
# 为节点设置图标
if key == "任正非":
child.setIcon(0, QtGui.QIcon("image/华为.png"))
elif key == "马云":
child.setIcon(0, QtGui.QIcon("image/阿里巴巴.png"))
elif key == "马化腾":
child.setIcon(0, QtGui.QIcon("image/腾讯.png"))
elif key == "李彦宏":
child.setIcon(0, QtGui.QIcon("image/百度.png"))
elif key == "董明珠":
child.setIcon(0, QtGui.QIcon("image/格力.png"))
child.setCheckState(0, QtCore.Qt.Checked) # 为节点设置复选框,并且选中
self.treeWidget.addTopLevelItem(root) # 将创建的树节点添加到树控件中
self.treeWidget.expandAll() # 展开所有节点
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "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_())
运行效果如下,树控件的奇数行为浅灰色背景,而偶数行为白色背景:
5. 获取选中节点的文本
获取选中节点的文本时,首先需要使用currentItem()方法获取当前的选中项,然后通过text()方法获取指定列的文本。
示例:在上一示例基础上定义槽函数,显示单击的树节点文本
关键代码如下:
# 为树控件的clicked信号绑定自定义的槽函数,以便在单击树控件时发射:
self.treeWidget.clicked.connect(self.gettreetext)
# 自定义槽函数
def gettreetext(self, index):
item = self.treeWidget.currentItem() # 获取当前选中项
from PyQt5.QtWidgets import QMessageBox
# 弹出提示框,显示选中项的文本
QtWidgets.QMessageBox.information(MainWindow, "提示", "您选择的是:%s -- %s" % (item.text(0), item.text(1)), QtWidgets.QMessageBox.Ok)
完整代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QTreeWidgetItem
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(400, 300)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.treeWidget = QtWidgets.QTreeWidget(self.centralwidget)
self.treeWidget.setGeometry(QtCore.QRect(0, 0, 400, 300))
self.treeWidget.setObjectName("treeWidget")
self.treeWidget.setColumnCount(2) # 设置树结构中的列数
self.treeWidget.setHeaderLabels(["姓名", "职务"]) # 设置列标题名
# 设置隔行变色
self.treeWidget.setAlternatingRowColors(True)
root = QTreeWidgetItem(self.treeWidget) # 创建节点
root.setText(0, "组织结构") # 设置顶级节点文本
# 定义字典,存储树中显示的数据
dict = {"任正非": "华为董事长", "马云": "阿里巴巴创始人", "马化腾": "腾讯 CEO", "李彦宏": "百度 CEO", "董明珠": "格力董事长"}
for key, value in dict.items(): # 遍历字典
child = QTreeWidgetItem(root) # 创建子节点
child.setText(0, key) # 设置第一列的值
child.setText(1, value) # 设置第二列的值
# 为节点设置图标
if key == "任正非":
child.setIcon(0, QtGui.QIcon("image/华为.png"))
elif key == "马云":
child.setIcon(0, QtGui.QIcon("image/阿里巴巴.png"))
elif key == "马化腾":
child.setIcon(0, QtGui.QIcon("image/腾讯.png"))
elif key == "李彦宏":
child.setIcon(0, QtGui.QIcon("image/百度.png"))
elif key == "董明珠":
child.setIcon(0, QtGui.QIcon("image/格力.png"))
child.setCheckState(0, QtCore.Qt.Checked) # 为节点设置复选框,并且选中
self.treeWidget.addTopLevelItem(root) # 将创建的树节点添加到树控件中
self.treeWidget.expandAll() # 展开所有节点
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
# 为树控件的clicked信号绑定自定义的槽函数,以便在单击树控件时发射:
self.treeWidget.clicked.connect(self.gettreetext)
# 自定义槽函数
def gettreetext(self, index):
item = self.treeWidget.currentItem() # 获取当前选中项
from PyQt5.QtWidgets import QMessageBox
# 弹出提示框,显示选中项的文本
QtWidgets.QMessageBox.information(MainWindow, "提示", "您选择的是:%s -- %s" % (item.text(0), item.text(1)), QtWidgets.QMessageBox.Ok)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "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_())
运行效果如下:
3. 分割控件
分割类控件主要对窗口中的区域进行功能划分,使窗口看起来更加合理、美观,PyQt5提供了分割线和弹簧两种类型的分割控件。
1. 分割线:QFrame
PyQt5提供了两个分割线控件,分别是水平分割线HorizontalLine和垂直分割线VerticalLine,但这两个分割线控件对应的类都是QFrame类,该类提供了一个setFrameShape()方法,通过设置该方法的参数,可以将分割线显示为水平或者垂直。
QFrame类的常用方法及说明
方法 | 说明 |
setFrameShape() |
|
setFrameShadow() |
|
setLineWidth() | 设置分割线的宽度。 |
setMidLineWidth() | 设置分割线的中间线宽度。 |
示例:PyQT5窗口中的分割线展示
在Qt Designer设计器中创建一个窗口,在窗口中添加8个Label控件,分别用来作为区域和分割线的标识;添加3个HorizontalLine水平分割线和4个VerticalLine垂直分割线,其中,用3个HorizontalLine水平分割线和3个VerticalLine垂直分割线显示分割线的各种样式,而剩余的一个VerticalLine垂直分割线用来将窗口分成两个区域。
关键代码如下:
# 添加水平分割线,并设置样式为Sunken,表示有下沉显示的边框阴影:
self.line_2 = QtWidgets.QFrame(self.centralwidget)
self.line_2.setGeometry(QtCore.QRect(90, 75, 201, 31))
self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_2.setLineWidth(8)
self.line_2.setMidLineWidth(8)
self.line_2.setObjectName("line_2")
# 添加水平分割线,并设置样式为Plain,表示无阴影:
self.line_3 = QtWidgets.QFrame(self.centralwidget)
self.line_3.setGeometry(QtCore.QRect(90, 140, 201, 31))
self.line_3.setFrameShape(QtWidgets.QFrame.HLine)
self.line_3.setFrameShadow(QtWidgets.QFrame.Plain)
self.line_3.setLineWidth(8)
self.line_3.setMidLineWidth(8)
self.line_3.setObjectName("line_3")
# 添加水平分割线,并设置样式为Raised,表示有凸起显示的边框阴影:
self.line_4 = QtWidgets.QFrame(self.centralwidget)
self.line_4.setGeometry(QtCore.QRect(90, 210, 201, 31))
self.line_4.setFrameShape(QtWidgets.QFrame.HLine)
self.line_4.setFrameShadow(QtWidgets.QFrame.Raised)
self.line_4.setLineWidth(8)
self.line_4.setMidLineWidth(8)
self.line_4.setObjectName("line_4")
# 添加垂直分割线,并设置样式为Sunken,表示有下沉显示的边框阴影:
self.line_5 = QtWidgets.QFrame(self.centralwidget)
self.line_5.setGeometry(QtCore.QRect(403, 70, 41, 151))
self.line_5.setFrameShape(QtWidgets.QFrame.VLine)
self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_5.setLineWidth(4)
self.line_5.setMidLineWidth(4)
self.line_5.setObjectName("line_5")
# 添加垂直分割线,并设置样式为Plain,表示无阴影:
self.line_6 = QtWidgets.QFrame(self.centralwidget)
self.line_6.setGeometry(QtCore.QRect(520, 70, 41, 151))
self.line_6.setFrameShape(QtWidgets.QFrame.VLine)
self.line_6.setFrameShadow(QtWidgets.QFrame.Plain)
self.line_6.setLineWidth(4)
self.line_6.setMidLineWidth(4)
self.line_6.setObjectName("line_6")
# 添加垂直分割线,并设置样式为Raised,表示有凸起显示的边框阴影:
self.line_7 = QtWidgets.QFrame(self.centralwidget)
self.line_7.setGeometry(QtCore.QRect(650, 70, 41, 151))
self.line_7.setFrameShape(QtWidgets.QFrame.VLine)
self.line_7.setFrameShadow(QtWidgets.QFrame.Raised)
self.line_7.setLineWidth(4)
self.line_7.setMidLineWidth(4)
self.line_7.setObjectName("line_7")
完整代码如下:
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(755, 320)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(20, 10, 121, 16))
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setGeometry(QtCore.QRect(480, 10, 91, 16))
self.label_2.setObjectName("label_2")
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setGeometry(QtCore.QRect(20, 80, 72, 15))
self.label_3.setObjectName("label_3")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setGeometry(QtCore.QRect(20, 150, 72, 15))
self.label_4.setObjectName("label_4")
self.label_5 = QtWidgets.QLabel(self.centralwidget)
self.label_5.setGeometry(QtCore.QRect(20, 220, 72, 15))
self.label_5.setObjectName("label_5")
self.label_6 = QtWidgets.QLabel(self.centralwidget)
self.label_6.setGeometry(QtCore.QRect(400, 240, 72, 15))
self.label_6.setObjectName("label_6")
self.label_7 = QtWidgets.QLabel(self.centralwidget)
self.label_7.setGeometry(QtCore.QRect(530, 240, 72, 15))
self.label_7.setObjectName("label_7")
self.label_8 = QtWidgets.QLabel(self.centralwidget)
self.label_8.setGeometry(QtCore.QRect(650, 240, 72, 15))
self.label_8.setObjectName("label_8")
self.line = QtWidgets.QFrame(self.centralwidget)
self.line.setGeometry(QtCore.QRect(330, 0, 20, 321))
self.line.setFrameShape(QtWidgets.QFrame.VLine)
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
# 添加水平分割线,并设置样式为Sunken,表示有下沉显示的边框阴影:
self.line_2 = QtWidgets.QFrame(self.centralwidget)
self.line_2.setGeometry(QtCore.QRect(90, 75, 201, 31))
self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_2.setLineWidth(8)
self.line_2.setMidLineWidth(8)
self.line_2.setObjectName("line_2")
# 添加水平分割线,并设置样式为Plain,表示无阴影:
self.line_3 = QtWidgets.QFrame(self.centralwidget)
self.line_3.setGeometry(QtCore.QRect(90, 140, 201, 31))
self.line_3.setFrameShape(QtWidgets.QFrame.HLine)
self.line_3.setFrameShadow(QtWidgets.QFrame.Plain)
self.line_3.setLineWidth(8)
self.line_3.setMidLineWidth(8)
self.line_3.setObjectName("line_3")
# 添加水平分割线,并设置样式为Raised,表示有凸起显示的边框阴影:
self.line_4 = QtWidgets.QFrame(self.centralwidget)
self.line_4.setGeometry(QtCore.QRect(90, 210, 201, 31))
self.line_4.setFrameShape(QtWidgets.QFrame.HLine)
self.line_4.setFrameShadow(QtWidgets.QFrame.Raised)
self.line_4.setLineWidth(8)
self.line_4.setMidLineWidth(8)
self.line_4.setObjectName("line_4")
# 添加垂直分割线,并设置样式为Sunken,表示有下沉显示的边框阴影:
self.line_5 = QtWidgets.QFrame(self.centralwidget)
self.line_5.setGeometry(QtCore.QRect(403, 70, 41, 151))
self.line_5.setFrameShape(QtWidgets.QFrame.VLine)
self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_5.setLineWidth(4)
self.line_5.setMidLineWidth(4)
self.line_5.setObjectName("line_5")
# 添加垂直分割线,并设置样式为Plain,表示无阴影:
self.line_6 = QtWidgets.QFrame(self.centralwidget)
self.line_6.setGeometry(QtCore.QRect(520, 70, 41, 151))
self.line_6.setFrameShape(QtWidgets.QFrame.VLine)
self.line_6.setFrameShadow(QtWidgets.QFrame.Plain)
self.line_6.setLineWidth(4)
self.line_6.setMidLineWidth(4)
self.line_6.setObjectName("line_6")
# 添加垂直分割线,并设置样式为Raised,表示有凸起显示的边框阴影:
self.line_7 = QtWidgets.QFrame(self.centralwidget)
self.line_7.setGeometry(QtCore.QRect(650, 70, 41, 151))
self.line_7.setFrameShape(QtWidgets.QFrame.VLine)
self.line_7.setFrameShadow(QtWidgets.QFrame.Raised)
self.line_7.setLineWidth(4)
self.line_7.setMidLineWidth(4)
self.line_7.setObjectName("line_7")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "水平分割线"))
self.label_2.setText(_translate("MainWindow", "垂直分割线"))
self.label_3.setText(_translate("MainWindow", "Sunken:"))
self.label_4.setText(_translate("MainWindow", "Plain:"))
self.label_5.setText(_translate("MainWindow", "Raised:"))
self.label_6.setText(_translate("MainWindow", "Sunken"))
self.label_7.setText(_translate("MainWindow", "Plain"))
self.label_8.setText(_translate("MainWindow", "Raised"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
MainWindow.show()
ui.setupUi(MainWindow)
sys.exit(app.exec_())
运行结果如下:
2. 弹簧:QSpacerItem
PyQt5提供了两个弹簧控件,分别是HorizontalSpacer和VerticalSpacer,但这两个控件对应的类都是QSpacerItem类,水平和垂直主要通过宽度和高度(水平弹簧的默认宽度和高度分别是40、20,而垂直弹簧的默认宽度和高度分别是20、40)进行区分。
QSpacerItem弹簧主要用在布局管理器中,用来使布局管理器中的控件布局更加合理。
示例:使用弹簧控件改变控件位置
在Qt Designer设计器中创建一个窗口,在窗口中添加一个VerticalLayout垂直布局管理器,并向该布局管理器中任意添加控件,默认都是从下往上排列。
在垂直布局管理器中添加控件的设计效果:
在垂直布局管理器中添加控件的运行效果:
如果想要在垂直布局管理器中改变某个控件的位置,默认是无法改变的,那么怎么办呢?PyQt5提供了弹簧控件来方便开发人员能够根据自身需求更合理地摆放控件的位置。例如,通过应用弹簧对控件位置进行改动。使用弹簧更改控件位置的设计效果:
使用弹簧更改控件位置的运行效果:
弹簧控件只在设计窗口时显示,在实际运行时不显示。
4. 其他控件
除了前面的一些常用控件之外,PyQt5还提供了一些比较有特色的控件。
1. Dial:旋钮控件
Dial控件,又称为旋钮控件,它本质上类似于一个滑块控件,只是显示的样式不同。
Dial控件对应PyQt5中的QDial类。
QDial控件常用方法及说明
方法 | 说明 |
setFixedSize() | 设置旋钮的大小 |
setRange() | 设置表盘的数值范围 |
setMinimum() | 设置最小值 |
setMaximum() | 设置最大值 |
setNotchesVisible() | 设置是否显示刻度 |
示例:使用旋钮控制标签中的字体大小
使用Dial控件实现与前面QSlider滑块设置标签中文字大小类似的功能。
完整代码如下:
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(402, 122)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# 添加一个垂直布局管理器,用来显示文字
self.horizontalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(130, 20, 251, 81))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(self.horizontalLayoutWidget)
# 设置Label标签水平左对齐,垂直居中对齐
self.label.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
# 添加Dial控件
self.dial = QtWidgets.QDial(self.centralwidget)
self.dial.setGeometry(QtCore.QRect(20, 20, 71, 71))
self.dial.setMinimum(8) # 设置最小值为8
self.dial.setMaximum(72) # 设置最大值为72
self.dial.setNotchesVisible(True) # 设置刻度
self.dial.setObjectName("dial")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
# 为旋钮控件绑定valueChanged信号,在值发生更改时发射
self.dial.valueChanged.connect(self.setfontsize)
# 定义槽函数,根据旋钮的值改变Label控件的字体大小
def setfontsize(self):
value = self.dial.value() # 获取旋钮的值
self.label.setFont(QtGui.QFont("楷体", value)) # 设置Label的字体和大小
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "敢想敢为"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
MainWindow.show()
ui.setupUi(MinWindow)
sys.exit(app.exec_())
运行程序,默认效果如图所示:当用鼠标拖改:
变旋钮的刻度值时,Label标签中的文字大小也会发生改变:
2. 滚动条:QScrollBar
PyQt5提供了两个滚动条控件,分别是水平滚动条HorizontalScrollBar和垂直滚动条VerticalScrollBar,但这两个滚动条控件对应的类都是QScrollBar类,这两个控件通过水平的或垂直的滚动条,可以扩大当前窗口的有效装载面积,从而装载更多的控件。
QScrollBar滚动条类的常用方法及说明
方法 | 说明 |
setMinimum() | 设置滚动条最小值。 |
setMaximum() | 设置滚动条最大值。 |
setOritentation() |
|
setValue() | 设置滚动条的值。 |
value() | 获取滚动条的当前值。 |
QScrollBar滚动条类的常用信号及说明
信号 | 说明 |
信号 | 说明 |
valueChanged | 当滚动条的值发生改变时发射该信号 |
sliderMoved | 当用户拖动滚动条的滑块时发射该信号 |
将水平滚动条和垂直滚动条拖放到PyQt5窗口中的效果如图所示:
滚动条控件通常与其他控件配合使用,如ScrollArea、TableWidget表格等,另外,也可以使用滚动条控件实现与滑块控件同样的功能,实际上,滚动条控件也是一种特殊的滑块控件。