核心概念
PySide作为Qt官方Python绑定的GUI工具包,其强劲功能建立在几个核心概念之上。
如果你之前有Qt的开发经验信任很好理解,但是如果你没有那么理解起来可能有些困难,不用担心,仔细阅读我的描述和分析例程代码,就能完全掌握。
第一我们讲几个核心概念用表格的方式总结出来方便记忆。
|
核心概念 |
核心类/机制 |
主要功能与特点 |
|
应用与事件循环 |
QApplication |
管理应用程序的生命周期、主事件循环和系统级设置。每个GUI应用必须有且只有一个实例。 |
|
窗口与控件基础 |
QWidget |
所有用户界面对象的基类,提供坐标几何、绘制、事件处理等基础功能。 |
|
界面布局管理 |
QLayout及其子类 (如 QVBoxLayout) |
自动排列和调整控件位置与大小,确保界面布局整洁且适应窗口尺寸变化。 |
|
对象间通信 |
信号与槽 (Signals & Slots) |
Qt的核心机制,用于对象间松散耦合的通信。当事件发生时(如按钮被点击),控件发出信号,与之连接的槽函数(一般是你写的处理逻辑)会自动执行。 |
|
数据与显示分离 |
Model-View 架构 |
将数据(Model)的管理和数据的显示(View)分离,使数据变更可以自动同步到视图,且一个模型可为多个视图提供数据。 |
QApplication 与事件循环
任何PySide图形界面应用程序的起点都是创建**QApplication**实例,它负责管理应用程序的控制流、主事件循环和全局设置。
- 关键角色:处理来自窗口系统和其他来源的所有事件(如鼠标点击、键盘输入),并将它们分派给相应的窗口部件。它还负责应用程序的初始化和清理工作。
- 事件循环:通过调用 app.exec()启动事件循环。这是一个“无限”循环,不断检查是否有事件发生并处理,直到收到退出指令(如主窗口关闭)。没有它,界面会一闪而过,程序立即退出。
一个典型的程序入口代码如下:
import sys
from PySide6.QtWidgets import QApplication, QWidget
app = QApplication(sys.argv)# 创建应用实例,可处理命令行参数
# ... (创建窗口和其他控件)
window.show()# 显示窗口
sys.exit(app.exec())# 进入事件循环,并将退出代码传递给系统
QWidget 与窗口部件
QWidget 类是所有用户界面对象的基类。按钮、标签、对话框、主窗口——几乎所有你在屏幕上看到的界面元素都是QWidget或其子类。
- 窗口与部件:一个没有父部件的 QWidget一般是一个窗口(带有系统边框和标题栏)。有父部件的 QWidget则作为容器或其他窗口内部的子控件存在。
- 几何管理:QWidget提供了管理自身位置和大小的方法,如 resize(), move(), 和 setGeometry()。
- 常用窗口类: QMainWindow:为典型的主应用程序窗口提供了预定义的布局结构,包括菜单栏、工具栏、状态栏和一个可放置中心部件的区域。 QDialog:主要用于创建短期存在的对话框窗口,例如“打开文件”或“设置偏好”对话框。
布局管理器
手动为每个控件设置绝对坐标 (move(x, y)) 既繁琐又难以维护,尤其在窗口大小改变时界面会变得混乱。布局管理器 解决了这个问题,它能自动安排控件的位置和大小。
- 工作原理:你将控件添加到布局管理器(如 QVBoxLayout垂直排列,QHBoxLayout水平排列,QGridLayout网格排列),然后将该布局管理器设置给一个父 QWidget。布局管理器会负责控件的排列和当父窗口调整大小时的重绘。
- 优势:保证界面元素排列整齐,自适应窗口尺寸变化,支持布局嵌套以构建复杂界面。
这里我总结四种核心布局管理器的特点和典型用途:
|
布局类型 |
核心类 |
排列方式 |
适用场景 |
|
水平布局 |
QHBoxLayout |
从左到右水平排列控件 |
工具栏、一行按钮、水平排列的表单 |
|
垂直布局 |
QVBoxLayout |
从上到下垂直排列控件 |
设置对话框、侧边栏、垂直排列的列表 |
|
网格布局 |
QGridLayout |
在行和列组成的网格中排列控件 |
数据表格、计算器界面、复杂的仪表盘 |
|
表单布局 |
QFormLayout |
两列布局(一般左标签右输入) |
用户注册、设置、数据录入等表单界面 |
后面我们会专门学习使用布局管理器,这里就不提供代码了。
信号与槽机制
这是Qt框架最突出的特性之一,实现了对象之间的高效、松散耦合的通信。
- 信号:当某个特定事件发生在对象上时(例如按钮被点击 clicked,滑块值改变 valueChanged),该对象会发射一个信号。信号本身不执行任何操作。
- 槽:槽是一个可以被调用的函数(或方法)。你负责编写槽函数来定义当特定信号发出时应发生什么。
- 连接:使用 信号发射者.信号名.connect(槽函数)将信号与槽关联起来。一旦连接建立,当信号发射时,对应的槽函数便会自动执行。
这里我提供一个代码示例,通过点击按钮弹出消息框的简单程序,可以体验信号和槽机制。
from PySide6.QtWidgets import QApplication, QPushButton, QMessageBox
def on_button_clicked():
QMessageBox.information(window, "提示", "按钮被点击了!")
app = QApplication([])
button = QPushButton("点击我")
button.clicked.connect(on_button_clicked) # 连接信号与槽
button.show()
app.exec()
Model-View 架构
对于显示列表、表格或树形等结构化数据,Qt推荐使用Model-View架构。这种架构将数据本身(Model)和数据的可视化呈现(View)分离开来。
- Model:负责数据的存储、访问和底层逻辑。Qt提供了如 QStandardItemModel等标准模型,你也可以自定义模型。
- View:负责将模型中的数据以某种形式(如列表、表格)显示给用户,并处理用户的显示交互。
- 优势: 分离关注点:数据逻辑和显示逻辑独立,便于维护和扩展。 一致性:同一个数据模型可以同时用于多个不同的视图(例如,一份数据既用表格显示,又用图表显示)。 高效处理大数据:对于大型数据集,Qt的视图部件经过优化,可以只渲染可见部分,性能更好。
Model-View 是超级重大的GUI开发思想,虽然我们才刚开始学习GUI开发,但是也需要超级了解,这里为了便于大家理解,我提供一个简单的例子,用来说明Model-View 架构。
import sys
from PySide6.QtCore import Qt
from PySide6.QtGui import QStandardItemModel, QStandardItem, QIcon
from PySide6.QtWidgets import (QApplication, QMainWindow, QListView,
QVBoxLayout, QHBoxLayout, QLineEdit,
QPushButton, QWidget, QAbstractItemView)
class TodoModel(QStandardItemModel):
"""自定义模型,管理待办事项数据"""
def add_item(self, text):
"""向模型添加一个新的待办事项"""
if not text.strip():
return
item = QStandardItem(text)
item.setCheckable(True) # 让项目可以被勾选
item.setEditable(False) # 禁止直接编辑
# 初始状态为未完成(未勾选)
item.setCheckState(Qt.Unchecked)
self.appendRow(item)
def remove_selected_item(self, index):
"""从模型中移除选定的项目"""
if index.isValid():
self.removeRow(index.row())
def toggle_completion(self, index):
"""切换项目的完成状态(可选扩展功能)"""
if index.isValid():
item = self.itemFromIndex(index)
# 这里可以根据需要添加更复杂的完成状态逻辑
current_state = item.checkState()
new_state = Qt.Checked if current_state == Qt.Unchecked else Qt.Unchecked
item.setCheckState(new_state)
class TodoView(QListView):
"""自定义视图,显示待办事项列表"""
def __init__(self, model):
super().__init__()
self.setModel(model) # 设置模型
self.setSelectionMode(QAbstractItemView.SingleSelection) # 设置为单选模式
class MainWindow(QMainWindow):
"""主窗口,充当控制器的角色"""
def __init__(self):
super().__init__()
self.setWindowTitle("简易待办事项列表 - PySide6 MVC示例")
self.resize(400, 500)
# 初始化模型和视图
self.model = TodoModel()
self.view = TodoView(self.model)
# 创建UI控件
self.input_field = QLineEdit()
self.input_field.setPlaceholderText("输入新的待办事项...")
self.input_field.returnPressed.connect(self.add_item) # 按回车键添加
self.add_button = QPushButton("添加")
self.add_button.clicked.connect(self.add_item)
self.delete_button = QPushButton("删除选中")
self.delete_button.clicked.connect(self.delete_item)
# 设置布局
input_layout = QHBoxLayout()
input_layout.addWidget(self.input_field)
input_layout.addWidget(self.add_button)
button_layout = QHBoxLayout()
button_layout.addWidget(self.delete_button)
main_layout = QVBoxLayout()
main_layout.addWidget(self.view)
main_layout.addLayout(input_layout)
main_layout.addLayout(button_layout)
container = QWidget()
container.setLayout(main_layout)
self.setCentralWidget(container)
def add_item(self):
"""处理添加新待办事项的逻辑"""
text = self.input_field.text()
self.model.add_item(text)
self.input_field.clear() # 清空输入框
def delete_item(self):
"""处理删除选中待办事项的逻辑"""
current_index = self.view.currentIndex()
self.model.remove_selected_item(current_index)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
这个示例清晰地展示了MVC架构的三个核心部分:
- 模型 (Model – TodoModel): 继承自 QStandardItemModel,负责管理应用程序的数据。 提供了 add_item, remove_selected_item等方法来操作数据。 数据变化会自动通知视图更新。
- 视图 (View – TodoView): 继承自 QListView,负责将模型中的数据呈现给用户。 通过 setModel()方法与模型关联。 处理用户的界面交互,如选择项目。
- 控制器 (Controller – MainWindow): 协调模型和视图之间的交互。 包含UI控件(按钮、输入框)并连接它们的信号(如 clicked, returnPressed)到相应的槽函数(如 add_item, delete_item)。 当用户执行操作时,控制器调用模型的方法来更新数据,视图会自动更新以反映这些变化。
总结
QApplication驱动整个应用的生命周期和事件处理;QWidget及其子类构成界面的基本元素;布局管理器 负责这些元素的优雅排列;信号与槽 机制让这些元素能够响应用户交互并进行通信;Model-View 架构则为复杂数据的展示提供了清晰、高效的解决方案。


收藏了,感谢分享