第 81 课:进阶 GUI:PyQt/PySide 简介
所属模块:模块十五:GUI编程 难度:Advanced 标签:gui, pyqt, pyside, qt 上一课:Tkinter 事件处理与绑定 下一课:项目打包与分发:setuptools 入门
学习目标
完成本课学习后,你将能够:
- 理解 PyQt 和 PySide 框架的关系、区别及选择依据。
- 掌握 Qt 框架中"信号与槽"这一核心机制的基本原理和用法。
- 熟练运用 Qt Designer 快速设计界面并加载到 Python 代码中。
- 创建包含常用控件(如按钮、标签、输入框)并具有基本交互功能的桌面应用程序。
- 了解使用 Qt 框架进行 GUI 开发相比 Tkinter 的优势与适用场景。
核心概念
欢迎来到 GUI 编程的进阶阶段!Tkinter 是 Python 内置的、轻量级的 GUI 工具包,非常适合入门和简单应用。但当你的应用变得复杂,或者你追求更专业、更美观、功能更强大的界面时,基于 Qt 框架的解决方案就成了更好的选择。
1. PyQt 与 PySide:两条通往 Qt 的路
Qt 是一个用 C++ 编写、功能极其强大的跨平台应用程序框架。它不仅仅是一个 GUI 库,还包含了网络、数据库、多媒体等众多模块。要在 Python 中使用 Qt,主要有两个官方绑定库:
- PyQt:由 Riverbank Computing 开发维护。它是一个商业软件,但在开发开源或 GPL 许可的应用时可以免费使用。它的 API 设计非常 Pythonic。
- PySide:由 Qt 公司(原 Digia)官方推出的 Python 绑定。它在 LGPL 许可下发布,这意味着你可以在开发商业闭源软件时免费使用它。其 API 与 PyQt 非常相似。
如何选择? 如果你的项目是开源且愿意遵循 GPL 协议,两者皆可。如果计划开发商业软件,PySide(LGPL) 是更常见的选择,因为其许可更宽松。在语法层面,除了个别类名和模块导入方式略有不同(如 PyQt5.QtWidgets vs PySide6.QtWidgets),大部分代码可以轻松移植。本课程将以 PySide6 为例进行讲解,因为其官方背景和许可优势。
2. 核心机制:信号与槽
这是 Qt 框架的灵魂。想象一个场景:你点击了一个按钮(发送一个"被点击"的信号),你希望程序弹出一个对话框(执行一个"弹出对话框"的槽函数)。
- 信号:由特定对象(如按钮、滑块)在特定事件(如点击、值改变)发生时发射。
- 槽:就是一个普通的 Python 函数或方法,用于响应特定的信号。
将信号与槽连接起来,就建立了对象间的通信。这比传统的回调函数更灵活、更安全。
# 伪代码概念展示
button = QPushButton("点击我")
# 当 button 发射 `clicked` 信号时,调用 my_function 槽函数
button.clicked.connect(my_function)
def my_function():
print("按钮被点击了!")
3. 界面构建方式
Qt 提供两种方式构建界面:
- 纯代码:像我们用 Tkinter 一样,通过 Python 代码一行行创建和布局控件。灵活,易于版本控制。
- Qt Designer:一个所见即所得的图形化界面设计工具。你可以拖拽控件来设计界面,然后保存为
.ui文件。在 Python 中可以通过uic.loadUi函数直接加载这个文件,将界面与业务逻辑代码分离,非常高效。
代码示例
下面是一个完整的 PySide6 应用示例,创建了一个带有一个标签和一个按钮的窗口。点击按钮,标签文字会改变。
# 文件:basic_pyside_example.py
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout, QWidget
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("我的第一个 PySide6 应用")
self.setGeometry(100, 100, 400, 200) # 设置窗口位置和大小(x, y, 宽, 高)
# 创建一个中心部件和布局
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
# 创建一个标签
self.label = QLabel("欢迎使用 PySide6!", self)
self.label.setStyleSheet("font-size: 18px; color: #333;") # 设置样式
layout.addWidget(self.label)
# 创建一个按钮
self.button = QPushButton("点击我")
self.button.setStyleSheet("font-size: 16px; padding: 10px;")
# **关键:连接信号与槽**
self.button.clicked.connect(self.on_button_clicked)
layout.addWidget(self.button)
# 也可以创建一个输入框,并连接它的回车信号
# self.input_box = QLineEdit()
# self.input_box.returnPressed.connect(self.on_input_submitted)
# layout.addWidget(self.input_box)
def on_button_clicked(self):
"""这是一个槽函数,当按钮被点击时调用"""
self.label.setText("按钮已被点击!信号与槽成功连接!")
# 应用程序的入口点
if __name__ == "__main__":
# 1. 创建一个 QApplication 实例。每个 PySide6 应用必须且只能有一个。
app = QApplication(sys.argv)
# 2. 创建主窗口实例
window = MainWindow()
# 3. 显示窗口
window.show()
# 4. 进入应用程序的主事件循环
sys.exit(app.exec())
代码解析:
- 我们创建了一个继承自
QMainWindow的自定义窗口类。 - 在
__init__中设置了窗口标题和几何信息。 - 使用了 布局管理器
QVBoxLayout来垂直排列控件(标签和按钮)。布局管理器是 Qt 强大的特性,能自动处理窗口缩放时的控件排列。 - 最关键的部分是
self.button.clicked.connect(self.on_button_clicked),它将按钮的clicked信号与我们的on_button_clicked方法连接起来。 - 最后,标准的启动流程:创建
QApplication-> 创建窗口 -> 显示窗口 -> 进入事件循环。
实践练习
练习 1:基础窗口与事件 创建一个程序,包含一个窗口和一个标签。标签初始文本为"计数器:0"。每次点击窗口(任何位置),标签的计数器数值增加1。
- 提示:你需要为窗口部件(
QWidget)的mousePressEvent事件重写,或者使用一个覆盖整个窗口的不可见按钮。 - 预期输出:每点击一次窗口,标签数字加1。
练习 2:输入与响应
在练习1的基础上,增加一个 QLineEdit 输入框和一个"设置"按钮。输入框用于输入姓名,点击"设置"按钮后,将主标签的文字更新为"你好,[输入的姓名]!"。
- 预期输出:输入"小明"并点击按钮,标签显示"你好,小明!"。
练习 3:探索 Qt Designer(可选高阶)
- 在终端安装
pyside6-tools(pip install pyside6-tools)。 - 打开
Qt Designer(通常在 Python 的 Scripts 目录下,如pyside6-designer.exe)。 - 设计一个包含"用户名"、"密码"输入框和"登录"、"取消"按钮的登录界面。
- 将设计保存为
login.ui。 - 编写 Python 代码,使用
uic.loadUi加载此文件,并为"登录"按钮连接一个简单的槽函数(例如,在控制台打印"登录按钮被点击")。
常见错误
- 忘记调用
window.show():窗口创建后,必须显式调用show()方法才能将其显示在屏幕上。这是新手最常犯的错误之一。 - 信号连接错误:
- 写错了信号名(如
clicked写成click)。 - 写错了槽函数名,或槽函数没有正确的
self参数。 - 尝试连接一个不存在的信号。
- 写错了信号名(如
- 布局管理混乱:试图直接通过
widget.move(x, y)来定位所有控件,而没有使用布局管理器。这会导致窗口缩放时界面错乱。优先使用布局管理器。 - PyQt/PySide 导入混淆:PyQt5 的模块是
PyQt5.QtWidgets,PySide6 是PySide6.QtWidgets。混用会导致导入错误。 - 没有创建
QApplication:在实例化任何 Qt 控件(如QMainWindow)之前,必须先创建QApplication实例。
小结
本节课我们迈入了专业级 GUI 开发的大门:
- 框架认知:了解了 PyQt 和 PySide 是 Python 访问强大 Qt 框架的两种主要途径,并知道了如何根据项目许可进行选择。
- 核心机制:掌握了 Qt 的基石——信号与槽,理解了它是如何优雅地实现对象间通信的。
- 实战入门:通过一个完整的例子,学习了使用 PySide6 创建窗口、添加控件、连接信号与槽,以及处理基本布局的全过程。
- 工具链:了解了 Qt Designer 这个强大的辅助设计工具,它能极大提升复杂界面的开发效率。
掌握了 PyQt/PySide,你便拥有了开发跨平台(Windows, macOS, Linux)、外观现代化、功能强大且可扩展的桌面应用程序的能力。下一步,我们将学习如何将你的精美 GUI 程序打包并分发给用户。