主题
PyQt6
PyQt6 是一个Python的GUI库,它基于Qt5,并且使用PySide6作为底层库。
PyQt6 Digia 公司的 Qt 程序的 Python 中间件。Qt库是最强大的GUI库之一。PyQt6的官网:www.riverbankcomputing.co.uk/news。PyQt6是由Riverbank Computing公司开发的。
PyQt6 是基于 Python 的一系列模块。它是一个多平台的工具包,可以在包括Unix、Windows和Mac OS在内的大部分主要操作系统上运行。PyQt6 有两个许可证,开发人员可以在 GPL 和商业许可之间进行选择。
使用 - 安装
sh
$ pip install PyQt6
我们可以使用 pip
工具安装 PyQt6。除此之外,还可以安装 PyQt6-tools,使用 designer 设计师软件构建窗体页面,然后使用 PyUIC6 将 .ui 文件转换为 PyQt6 的代码。
shell
pip install PyQt6-tools
这两步若下载缓慢,可使用
pip install PyQt6 PyQt6-tools -i https://mirrors.aliyun.com/pypi/simple
安装。
有时,安装可能会遇到如下的错误。
Installing build dependencies ... done
Getting requirements to build wheel ... done
Preparing metadata (pyproject.toml) ... error
error: subprocess-exited-with-error
× Preparing metadata (pyproject.toml) did not run successfully.
│ exit code: 1
╰─> [26 lines of output]
这里可利用 StackOverflow上一个大神提供的方案解决。
- 从pypi下载该PyQt6-tools,链接为 https://pypi.org/project/PyQt6/#files 。下载 Windows 版本,如 PyQt6-6.4.1-cp37-abi3-win_amd64.whl 。
- 然后从pypi下载PyQt6-Plugins,链接为 https://pypi.org/project/pyqt6-plugins/#files 。下载 Windows 版本,如 pyqt6_plugins-6.1.0.2.2-cp39-cp39-win_amd64.whl 。
- 用WinRar (或类似的) 打开后一个文件,然后依次打开 "pyqt6_plugins-xxx.dist-info",用文本编辑器打开 METADATA 文件。
- 找到一行:"Requires-Dist: pyqt6(==6.1.0)"或类似的,并更改为"Requires-Dist: pyqt6"。保存文件。
- 最后手动安装这两个文件,先安装第一个,再安装第二个,命令为
pip install 文件名
源地址:https://stackoverflow.com/questions/72060996/cannot-install-pyqt6-tools-in-python-3-11-on-windows
了解 - PyQt6 模块
PyQt6 类是由一系列模块组成的,包括如下的模块:
- QtCore
- QtGui
- QtWidgets
- QtDBus
- QtNetwork
- QtHelp
- QtXml
- QtSvg
- QtSql
- QtTest
使用 - 第一个 PyQt6 窗体
先放代码。
python
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QMessageBox, QPushButton, QHBoxLayout, QWidget
app = QApplication([])
central_widget = QWidget()
window = QMainWindow()
window.setCentralWidget(central_widget)
button = QPushButton()
button.setText("点击我展示一个提示小窗口。")
button.clicked.connect(lambda: QMessageBox.information(window, "提示", "这是一个提示小窗口。"))
layout = QHBoxLayout(central_widget)
layout.addWidget(button)
window.show()
sys.exit(app.exec())
这段代码首先导入必要的模块和函数,然后创建了一个应用程序对象。PyQt6和很多框架一样,都需要在最开始创建一个应用程序对象,然后执行应用,窗体的有关功能才能执行。接下来就是创建一个窗体对象,这里窗体使用的是 QMainWindow,日常开发中如果窗体组件过多,推荐使用 QMainWindow。
接下来就是向窗体添加控件,这里添加了按钮,并且为了使按钮居中,使用 QHBoxLayout 布局,并且将按钮添加到布局中。
然后为按钮添加事件监听,当按钮被点击时,会弹出一个提示框。button.clicked
是一个函数,这个函数有一个 connect
方法,可以将按钮的点击事件连接到一个函数上。这里的点击事件就叫槽,函数就叫槽函数。
最后就是显示窗体和执行应用,由于 PyQt6 的应用对象 QApplication
是单例的,所以这里直接使用 sys.exit(app.exec())
。
使用 - 使用设计师软件设计窗体
若前面你根据我的教程安装了 PyQt6-tools 软件包,你可以在 PyQt6-tools 中找到一个名为 designer 的软件,这个软件可以设计窗体,然后生成对应的代码。
如果你使用 PyCharm 开发,使用 venv 作为虚拟环境,使用 pip 作为软件包管理工具,你可以在 <虚拟环境>/Lib/site-packages/qt6-Applications/Qt/bin/ 找到 designer.exe,它就是这里介绍的设计师软件。
这里简单介绍一下它的使用方法。
刚启动时,弹出一个引导界面,提示你要创建什么样的窗体,共有五个选项,也可以在这里找到已经保存的设计师文件。这里选择MainWindow。
默认创建的 MainWindow 包含一个菜单栏和一个导航栏。
创建完成后,左边的是组件列表,可以选择我们需要的组件,前面的 QPushButton 就在其中。中间的就是窗体预览和编辑处。
右边分为三部分,上面的是组件树,通过嵌套关系,我们就可以看出组件之间的层级关系。中间部分是属性管理器,它为我们展示了组件的所有属性,比如大小、文字、字体等,且支持编辑。下面是信号和槽管理器,以及资源管理器。
设计完主窗体后,点击菜单栏中的保存按钮,将 MainWindow.ui 文件保存到本地。
生成了 .ui 文件,还需要将 .ui 文件转换为可执行的 .py 文件,这里需要使用的一款工具就是 PyUIC6。
shell
pyuic6 -x MainWindow.ui -o MainWindow.py
执行这个命令后,就可以看到 MainWindow.py 文件了,运行此文件就可以看到窗体了。
使用 - 认识组件
可以看到,所有控件都继承自 QFrame,而 QFrame 继承自 QWidgets,QWidgets 的属性如大小、背景颜色、字体等,这些组件也都有,因此这里统一介绍一下比较常用的一些属性。
属性 | 说明 |
---|---|
enabled | 是否启用组件,不可用的组件会显示为灰色,并且不可操控 |
geometry | 组件的大小和位置,顺序依次是X、Y、宽度和高度。PyQt6的坐标系是从左上角开始的 |
minimumSize、maximumSize | 组件/窗体宽度和高度的最大值和最小值 |
styleSheet | 设定组件的样式表 |
这些属性为私有属性,若我们需要获取或改变这些属性,需要调用对应的 getter 或 setter 方法,如 button.setEnabled(True)
。
每个继承自 QWidget 类的控件,因其独特的功能,也会有属于自己的方法或属性,这些将在接下来的章节中介绍。
使用 - 信号与槽机制
Qt 中信号与槽就是事件监听的意思。
由于很多组件都继承自 QWidget,因此它们有一些公共的信号,但不常用。
这里虽然没有介绍具体的控件,但还是以按钮为例,介绍一下最常用的,按钮的“点击”信号如何和槽函数关联。
python
button.clicked.connect(function)
这里的 button 为 QPushButton 的实例,QPushButton 是一个可点击的按钮。
在 Qt 设计师软件中,依次点击导航栏上的【编辑】 - 【编辑信号/槽】,切换到此模式,然后点击按钮,并按住,拖拽出来,即可新建一个信号。
随后在弹出的对话框中,选中 clicked()
信号。这时候可以看到右侧没有任何槽函数,我们可以勾选“显示从 QWidget 继承的信号和槽”,并将 clicked()
和 close()
函数关联。
使用 PyUIC6 转换成 Python 代码后,便可看到信号与槽关联的代码片段,大概为:
python
self.pushButton.clicked.connect(MainWindow.close)
这里是将两个函数关联起来,clicked是一个函数,MainWindow.close也是一个函数。若我们自定义函数时,也需要传递函数对象。
槽函数亦可以解除关联,可以调用组件对象的 disconnect()
方法。
组件 - 按钮
按钮是 Qt 中的一类大组件,常用的有点击按钮、单选按钮、复选框,对应的类分别为 QPushButton、QRadioButton、QCheckBox。它们都继承自 QAbstractButton,所以有一些公共的属性和方法(继承自 QWidgets 的属性和方法在这里不再重复)。
属性或方法 | 说明 |
---|---|
text() 、setText(text) | 获取或设置按钮的显示文本 |
isChecked() 、setChecked() 、isCheckable() 、setCheckable() | 获取或设置按钮的选中状态,QPushButton不可用 |
它们的常用信号如下:
信号 | 说明 |
---|---|
clicked | 按钮被点击时触发 |
toggled | 按钮选中状态被改变时触发 |
pressed 、released | 按钮被按下和释放时触发 |
stateChanged | QCheckBox的选中状态被改变时触发,和 toggled 信号基本一致 |
示例代码:
python
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QRadioButton, QCheckBox, QVBoxLayout, QWidget, QMessageBox
app = QApplication([])
# 创建主窗口
window = QMainWindow()
# 创建中心部件,并设置为主窗口的中心部件
central_widget = QWidget()
window.setCentralWidget(central_widget)
# 创建按钮
button = QPushButton("点击我")
button.clicked.connect(lambda: QMessageBox.information(window, "按钮", "您点击了按钮"))
# 创建单选按钮
radio_button = QRadioButton("选择我")
radio_button.toggled.connect(lambda checked: print("单选按钮被选中" if checked else "单选按钮未选中"))
# 创建复选框
check_box = QCheckBox("勾选我")
check_box.stateChanged.connect(lambda state: print("复选框被选中" if state else "复选框未选中"))
# 创建垂直布局并设置为中心部件的布局
layout = QVBoxLayout(central_widget)
layout.addWidget(button)
layout.addWidget(radio_button)
layout.addWidget(check_box)
# 显示窗口
window.show()
# 运行应用程序
sys.exit(app.exec())
这里还需要介绍一下单选按钮如何实现互斥的操作,答案是将它们加入到按钮组 QButtonGroup 中,且可以默认选中一个单选按钮。
python
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QRadioButton, QCheckBox, QVBoxLayout, QWidget, QMessageBox, QButtonGroup
app = QApplication([])
# 创建主窗口
window = QMainWindow()
# 创建中心部件,并设置为主窗口的中心部件
central_widget = QWidget()
window.setCentralWidget(central_widget)
# 创建单选按钮
radio_button1 = QRadioButton("选择我")
radio_button2 = QRadioButton("选择另一个")
# 创建一个按钮组来管理单选按钮
button_group = QButtonGroup() # 创建QButtonGroup实例
button_group.addButton(radio_button1) # 将第一个单选按钮添加到组中
button_group.addButton(radio_button2) # 将第二个单选按钮添加到组中
# 创建垂直布局并设置为中心部件的布局
layout = QVBoxLayout(central_widget)
layout.addWidget(radio_button1)
layout.addWidget(radio_button2)
# 显示窗口
window.show()
# 运行应用程序
sys.exit(app.exec())
使用 - 展示控件 QLabel
QLabel 是 Qt 库中最基础的文本和图像展示控件之一。它可以用来显示纯文本或富文本,甚至可以用来展示图片。QLabel 非常灵活,可以根据需要调整其外观和行为。
QLabel的常用属性:
属性和方法 | 说明 |
---|---|
setText() 、text() | 设置或获取标签的文本内容 |
setAlignment(alignment) | 设置标签文本的对齐方式 |
setStyleSheet(style) | 设置标签的样式表 |
示例代码:
python
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QPixmap
from PyQt6.QtWidgets import QApplication, QLabel, QMainWindow, QVBoxLayout, QWidget
app = QApplication([])
# 创建主窗口
window = QMainWindow()
# 创建中心部件,并设置为主窗口的中心部件
central_widget = QWidget()
window.setCentralWidget(central_widget)
# 创建 QLabel 显示文本
text_label = QLabel("欢迎使用 PyQt6!")
text_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
text_label.setWordWrap(True)
# 创建 QLabel 显示图片
image_label = QLabel()
pixmap = QPixmap("example.png") # 假设 example.png 存在于当前目录下
image_label.setPixmap(pixmap)
image_label.setScaledContents(True)
# 创建垂直布局并设置为中心部件的布局
layout = QVBoxLayout(central_widget)
layout.addWidget(text_label)
layout.addWidget(image_label)
# 显示窗口
window.show()
# 运行应用程序
sys.exit(app.exec())
使用 - 布局
在 PyQt6 中,布局是用来管理窗口或控件内部的空间分配和控件排列的一种机制。使用布局可以帮助我们更容易地管理控件的位置和大小,同时也能保证控件在不同屏幕尺寸和分辨率下都能正确显示。Qt 提供了几种常见的布局管理器,包括 QHBoxLayout 和 QVBoxLayout,它们分别用于水平和垂直方向上的控件排列。
QHBoxLayout 是一个布局管理器,它负责在其容器内从左到右水平排列控件。当你希望控件横向排列时,可以使用 QHBoxLayout。
QVBoxLayout 则是在垂直方向上排列控件,从上到下。适合于需要垂直堆叠控件的情况。
常用方法:
- addWidget(widget):将一个控件添加到布局中。
- addStretch(stretch=0):添加一个拉伸空间,stretch 参数决定了空间的大小比例。
- addItem(item):添加一个布局项到布局中。
- setSpacing(spacing):设置控件之间的间距。
- setContentsMargins(left, top, right, bottom):设置布局的外边距。
- removeWidget(widget):从布局中移除一个控件。
- count():返回布局中控件的数量。
- itemAt(index):返回指定索引处的布局项。
示例:
python
import sys
from PyQt6.QtWidgets import QApplication, QPushButton, QLabel, QVBoxLayout, QHBoxLayout, QWidget, QMainWindow
app = QApplication([])
# 创建主窗口
window = QMainWindow()
# 创建中心部件,并设置为主窗口的中心部件
central_widget = QWidget()
window.setCentralWidget(central_widget)
# 创建按钮
button1 = QPushButton("按钮 1")
button2 = QPushButton("按钮 2")
button3 = QPushButton("按钮 3")
# 创建水平布局
h_layout = QHBoxLayout()
h_layout.addWidget(button1)
h_layout.addWidget(button2)
# 创建垂直布局
v_layout = QVBoxLayout()
v_layout.addLayout(h_layout) # 添加水平布局
v_layout.addWidget(button3)
v_layout.addWidget(QLabel("这是底部标签"))
# 设置中心部件的布局
central_widget.setLayout(v_layout)
# 显示窗口
window.show()
# 运行应用程序
sys.exit(app.exec())
设计师软件可以很方便地管理布局。在设计师软件中,选中已经预先排列好的控件,右击其中一个,然后在弹出的菜单中选择布局、选择你要的布局。
更多控件在这里不再演示。实际开发中,除文档中列出的控件外,还可以使用用于展示表格的QTableWidget、展示画布,可显示 MatPlotLib 图像的 QGraphicsView 等控件。