当前位置: 首页 > article >正文

PyQt学习系列02-模型-视图架构与数据管理

PyQt学习系列笔记(Python Qt框架)

第二课:PyQt的模型-视图架构与数据管理


一、模型-视图架构概述

1.1 什么是模型-视图架构?

模型-视图(Model-View)是Qt框架中用于数据展示和交互的核心设计模式。它将数据管理(模型)与用户界面(视图)分离,使得开发者可以灵活地处理复杂的数据操作,同时保持界面的简洁和高效。

核心组件

  • 模型(Model):负责存储和管理数据(如表格、列表、树形结构等)。
  • 视图(View):负责将数据以可视化形式展示给用户(如QTableViewQListView)。
  • 委托(Delegate):负责控制数据的编辑和显示方式(如单元格的外观和交互)。

优势

  1. 数据与界面解耦,便于维护和扩展。
  2. 支持多种数据源(内存数据、文件系统、数据库等)。
  3. 提供丰富的内置模型和视图组件,简化开发流程。

二、模型(Model)详解

2.1 模型的分类

PyQt提供了以下常用的模型类:

模型类功能
QStandardItemModel通用内存模型,支持表格、列表、树形结构
QFileSystemModel文件系统模型,用于浏览文件和目录
QSqlTableModel数据库模型,用于操作SQL数据库中的表

示例:创建一个QStandardItemModel并填充数据

from PyQt5.QtCore import QStandardItemModel, QStandardItem# 创建模型
model = QStandardItemModel(3, 2)  # 3行2列
model.setHorizontalHeaderLabels(["姓名", "年龄"])# 填充数据
model.setItem(0, 0, QStandardItem("张三"))
model.setItem(0, 1, QStandardItem("25"))
model.setItem(1, 0, QStandardItem("李四"))
model.setItem(1, 1, QStandardItem("30"))

2.2 模型的信号与槽

模型通过信号通知视图数据的变化,常见的信号包括:

  • dataChanged(index, index, role):数据项更新。
  • rowsInserted(parent, start, end):插入新行。
  • rowsRemoved(parent, start, end):删除行。

示例:监听数据变化

def on_data_changed(top_left, bottom_right, roles):print("数据已更新")model.dataChanged.connect(on_data_changed)

三、视图(View)详解

3.1 常用视图组件

视图类功能
QTableView表格视图,用于展示二维数据
QListView列表视图,用于展示一维数据
QTreeView树形视图,用于展示层次化数据

示例:使用QTableView展示数据

from PyQt5.QtWidgets import QApplication, QTableViewapp = QApplication([])
view = QTableView()
view.setModel(model)  # 绑定模型
view.show()
app.exec_()

3.2 视图的交互功能

视图支持多种用户交互操作:

  • 选择模式QAbstractItemView.SingleSelectionMultiSelection
  • 编辑模式QAbstractItemView.EditKeyPressedDoubleClicked
  • 排序功能:通过setSortingEnabled(True)启用排序。

示例:设置选择模式和排序

view.setSelectionMode(QAbstractItemView.MultiSelection)
view.setSortingEnabled(True)

四、委托(Delegate)详解

4.1 什么是委托?

委托(Delegate)是模型-视图架构中用于控制数据项的显示和编辑方式的组件。默认情况下,视图使用QStyledItemDelegate处理数据项,但开发者可以通过继承QItemDelegateQStyledItemDelegate自定义显示逻辑。

常见场景

  • 自定义单元格的样式(如颜色、字体)。
  • 实现复杂的编辑控件(如下拉框、日期选择器)。

示例:自定义委托(修改单元格背景色)

from PyQt5.QtWidgets import QStyledItemDelegate, QColorclass ColorDelegate(QStyledItemDelegate):def initStyleOption(self, option, index):super().initStyleOption(option, index)option.backgroundBrush = QColor("lightblue")  # 设置背景色view.setItemDelegate(ColorDelegate())

五、文件系统模型(QFileSystemModel)

5.1 功能概述

QFileSystemModel是Qt提供的用于操作文件系统的模型,支持浏览目录、文件属性、大小等信息。

常用方法

  • setRootPath(path):设置根目录。
  • filePath(index):获取指定索引的文件路径。
  • isDir(index):判断是否为目录。

示例:展示文件系统

from PyQt5.QtCore import QFileSystemModelfile_model = QFileSystemModel()
file_model.setRootPath(QDir.rootPath())  # 设置根目录为系统根目录
view.setModel(file_model)
view.setRootIndex(file_model.index("/"))  # 显示根目录下的内容

六、数据库模型(QSqlTableModel)

6.1 功能概述

QSqlTableModel是用于操作SQL数据库的模型,支持对数据库表的增删改查操作。

步骤

  1. 连接数据库。
  2. 创建QSqlTableModel并绑定表。
  3. 将模型绑定到视图。

示例:操作SQLite数据库

from PyQt5.QtSql import QSqlDatabase, QSqlTableModel# 连接数据库
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("test.db")
db.open()# 创建表
query = QSqlQuery()
query.exec_("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)")# 创建模型
model = QSqlTableModel(db=db)
model.setTable("users")
model.select()  # 加载数据# 绑定视图
view.setModel(model)
view.show()

七、自定义模型(继承QAbstractItemModel)

7.1 实现自定义模型

对于复杂的数据结构,开发者可以通过继承QAbstractItemModel实现自定义模型。需要重写以下方法:

  • index(row, column, parent):返回指定位置的索引。
  • parent(index):返回父索引。
  • rowCount(parent):返回行数。
  • columnCount(parent):返回列数。
  • data(index, role):返回数据项的内容。

示例:实现一个简单的树形模型

from PyQt5.QtCore import QAbstractItemModel, QModelIndex, Qtclass TreeModel(QAbstractItemModel):def __init__(self, data, parent=None):super().__init__(parent)self._data = data  # 数据结构为嵌套字典def index(self, row, column, parent=QModelIndex()):if not parent.isValid():parent_item = self._dataelse:parent_item = parent.internalPointer()child_item = parent_item.get("children", [])[row]return self.createIndex(row, column, child_item)def parent(self, index):if not index.isValid():return QModelIndex()child_item = index.internalPointer()parent_item = child_item.get("parent")if parent_item is None:return QModelIndex()return self.createIndex(parent_item.row(), 0, parent_item)def rowCount(self, parent=QModelIndex()):if not parent.isValid():parent_item = self._dataelse:parent_item = parent.internalPointer()return len(parent_item.get("children", []))def columnCount(self, parent=QModelIndex()):return 1def data(self, index, role=Qt.DisplayRole):if role == Qt.DisplayRole:item = index.internalPointer()return item.get("name")return None# 使用自定义模型
data = {"name": "根节点","children": [{"name": "子节点1", "parent": {"row": 0, "column": 0}},{"name": "子节点2", "parent": {"row": 0, "column": 0}}]
}
model = TreeModel(data)
view = QTreeView()
view.setModel(model)
view.show()

八、模型-视图的高级功能

8.1 筛选和排序

通过QSortFilterProxyModel可以实现数据的动态筛选和排序。

示例:实现模糊搜索

from PyQt5.QtCore import QSortFilterProxyModelproxy = QSortFilterProxyModel()
proxy.setSourceModel(model)
proxy.setFilterKeyColumn(0)  # 按第一列筛选
proxy.setFilterRegExp("张")  # 筛选包含"张"的行
view.setModel(proxy)

8.2 多线程加载数据

对于大数据量的模型,建议使用QThreadQFuture在后台线程加载数据,避免阻塞主线程。

示例:使用QThread加载数据

from PyQt5.QtCore import QThread, pyqtSignalclass DataLoader(QThread):data_loaded = pyqtSignal(list)def run(self):# 模拟耗时操作data = ["数据1", "数据2", "数据3"]self.data_loaded.emit(data)loader = DataLoader()
loader.data_loaded.connect(lambda data: model.update_data(data))
loader.start()

九、常见问题与解决方案

9.1 模型与视图的数据不同步

原因:模型未正确通知视图数据变化。
解决方法:确保在修改数据后调用model.dataChanged.emit()


9.2 视图无法显示自定义模型

原因:未正确实现index()parent()方法。
解决方法:检查索引生成逻辑,确保createIndex()的参数正确。


十、总结与下一步

本节课重点讲解了PyQt的模型-视图架构,包括:

  1. 模型(Model):数据管理的核心,支持多种数据源。
  2. 视图(View):数据展示的组件,如QTableView
  3. 委托(Delegate):控制数据的显示和编辑方式。
  4. 文件系统和数据库模型:快速集成文件和数据库操作。
  5. 自定义模型:通过继承QAbstractItemModel实现复杂数据结构。

下节课预告
第三课将深入讲解PyQt的动画与过渡效果,包括QPropertyAnimationQSequentialAnimationGroup的使用,以及如何为界面添加动态效果。请持续关注后续内容!


参考资料

  1. PyQt官方文档 - Model/View Programming
  2. Qt官方教程 - Model/View Framework
  3. CSDN PyQt5教程

相关文章:

PyQt学习系列02-模型-视图架构与数据管理

PyQt学习系列笔记(Python Qt框架) 第二课:PyQt的模型-视图架构与数据管理 一、模型-视图架构概述 1.1 什么是模型-视图架构? 模型-视图(Model-View)是Qt框架中用于数据展示和交互的核心设计模式。它将数…...

redis主从复制架构安装与部署

redis主从复制架构安装与部署 1、Redis 一主两从架构的优势2、环境准备3、下载redis4、解压缩文件5、编辑配置文件6、创建数据目录并启动Redis7、检查主从状态8、 Redis Sentinel 模式 1、Redis 一主两从架构的优势 Redis 采用一主两从(1个主节点 2个从节点&#…...

Kotlin 中 Lambda 表达式的语法结构及简化推导

在 Kotlin 编程中,Lambda 表达式是一项非常实用且强大的功能。今天,我们就来深入探讨一下 Lambda 表达式的语法结构,以及它那些令人 “又爱又恨” 的简化写法。 一、Lambda 表达式完整语法结构 Lambda 表达式最完整的语法结构定义为{参数名…...

YOLOv2 深度解析:目标检测领域的进阶之路

在计算机视觉领域,目标检测一直是研究和应用的热点方向。YOLO(You Only Look Once)系列算法以其快速高效的特点,在目标检测领域占据了重要地位。YOLOv2 作为 YOLO 系列算法的重要迭代版本,在 YOLOv1 的基础上进行了诸多…...

KT6368A通过蓝牙芯片获取手机时间详细说明,对应串口指令举例

一、功能简介 KT6368A双模蓝牙芯片支持连接手机,获取手机的日期、时间信息,可以同步RTC时钟 1、无需安装任何app,直接使用系统蓝牙即可实现 2、同时它不影响音频蓝牙,还支持一些简单的AT指令进行操作 3、实现的方式&#xff1…...

计算机网络实验课(二)——抓取网络数据包,并实现根据条件过滤抓取的以太网帧,分析帧结构

文章目录 一、添加控件二、代码分析2.1 代码2.2 控件初始化2.3 打开和关闭设备2.4 开始和结束捕获2.5 设置捕获条件2.6 捕获数据包 三、运行程序四、结果分析 提要:如果你通过vs打开.sln文件,然后代码界面或者前端界面都没找到,视图里面也没找…...

自动生成提示技术突破:AUTOPROMPT重塑语言模型应用

AUTOPROMPT 预训练语言模型的显著成功促使人们研究这些模型在预训练期间学习了哪些类型的知识。将任务重新表述为填空题(例如,完形填空测试)是衡量此类知识的自然方法 但是,它的使用受到编写合适提示所需的手动工作和猜测的限制。为了解决这个问题,我们开发了 AUTOPROMP…...

78. Subsets和90. Subsets II

目录 78.子集 方法一、迭代法实现子集枚举 方法二、递归法实现子集枚举 方法三、根据子集元素个数分情况收集 方法四、直接回溯法 90.子集二 方法一、迭代法实现子集枚举 方法二、递归法实现子集枚举 方法三、根据子集元素个数分情况收集 方法四、直接回溯法 78.子集…...

VSCode 插件 GitLens 破解方法

文章目录 1. 安装指定版本2. 修改插件文件3. 重启 VSCode 1. 安装指定版本 在 VSCode 中打开扩展(Ctrl Shift X),搜索 GitLens,右键点击 安装特定版本,在弹出的窗口中选择 17.0.2,然后等待安装完成。 2…...

linux 通过命令将 MinIO 桶的权限设置为 Custom(自定义策略)

在 Ubuntu 下,如果要通过命令将 MinIO 桶的权限设置为 Custom(自定义策略),可以使用 mc(MinIO Client)、AWS CLI 或直接调用 MinIO API(如 curl)。以下是几种方法: 方法 …...

模型评价指标介绍

模型评价指标介绍 **在机器学习与数据科学领域,构建模型仅是工作的一部分,更为关键的是要精准评估模型的性能。模型评价指标作为衡量模型表现的标准,有助于数据科学家、分析师等从业者判断模型的优劣,进而进行优化与改进。不同类…...

ElasticSearch整合SpringBoot

ElasticSearch 整合SpringBoot ES官方提供了各种不同语言的客户端。用来操作ES。这些客户端的本质就是组装DSL语句,通过HTTP请求发送给ES。 设计索引库 跟据数据库的表结构进行ES索引库的创建时。如果字段需要进行倒排索引的时候请为它指定分词器。如果该字段不是…...

ArcGIS Pro 3.4 二次开发 - 知识图谱

环境:ArcGIS Pro SDK 3.4 + .NET 8 文章目录 知识图谱1 知识图谱数据存储1.1 打开与知识图谱的连接1.2 从KnowledgeGraphLayer获取连接1.3 检索GDB要素类和定义1.4 检索GDB表和定义1.5 从知识图谱数据存储中获取服务 Uri1.6 将一组对象ID转换为实体的ID1.7 将一组ID转换为实体…...

2025上半年软考高级系统架构设计师经验分享

笔者背景 笔者在成都工作近7年, 一直担任研发大头兵,平日工作主要涵盖应用开发(Java)与数仓开发,对主流数据库、框架等均有涉猎,但谈不上精通。 最近有一些职业上的想法,了解到软考有那么一丁点…...

uni-app学习笔记十二-vue3中创建组件

通过组件,可以很方便地实现页面复用,减少重复页面的创建,减少重复代码。一个页面可以引入多个组件。下面介绍在HBuilder X中创建组件的方法: 一.组件的创建 1.选中项目,右键-->新建目录(文件夹),并将文…...

React 虚拟dom

虚拟dom react核心机制 内存中轻量级JS对象树模拟真实DOM,主要目的是减少操作真实dom的开销 具体是通过diff算法计算最小的变更,批处理更新真实dom元素 diff算法 特点 同级去进行比较,不涉及跨层的一个比较 使用key值优化列表遍历过程 …...

互联网大厂Java求职面试:AI与大模型应用集成中的架构难题与解决方案-1

互联网大厂Java求职面试:AI与大模型应用集成中的架构难题与解决方案-1 场景描述 郑薪苦,一个看似不靠谱但技术潜力巨大的程序员,在一次针对AI与大模型应用集成的面试中,被一位技术总监级别的人物提问。面试官以严肃专业的态度&a…...

《算法笔记》13.2小节——专题扩展->树状数组(BIT) 问题 D: 数列-训练套题T10T3

数列(sequence.pas/c/cpp) - 问题描述 一个简单的数列问题&#xff1a;给定一个长度为n的数列&#xff0c;求这样的三个元素ai, aj, ak的个数&#xff0c;满足ai < aj > ak&#xff0c;且i < j < k。 - 输入数据 第一行是一个整数n(n < 50000)。 第二行n个整…...

一键启动多个 Chrome 实例并自动清理的 Bash 脚本分享!

目录 一、&#x1f4e6; 脚本功能概览 二、&#x1f4dc; 脚本代码一览 三、&#x1f50d; 脚本功能说明 &#xff08;一&#xff09;✅ 支持批量启动多个 Chrome 实例 &#xff08;二&#xff09;✅ 每个实例使用独立用户数据目录 &#xff08;三&#xff09;✅ 启动后自…...

4 月 62100 款 App 被谷歌下架!环比增长 28%

大家好&#xff0c;我是牢鹅&#xff01;上周刚刚结束的 2025 年 Google I/O 开发者大会&#xff0c; Google Play 带来了一系列的更新&#xff0c;主要围绕提升优质 App 的"发现"、"互动"和"收入"三大核心内容。 这或许正是谷歌生态的一个侧影…...

图像分割全路线学习(结合论文)

本篇文章参考自开源大佬的文章并结合自己的思考而来&#xff0c;欢迎大家提出意见&#xff0c;论文代码同样来自开源&#xff0c;文中已注明 文章目录 图像分割图像分割算法分类&#xff1f;传统的基于CNN的分割方法缺点&#xff1f;FCN详解FCN改变了什么?FCN网络结构&#x…...

Go语言之定义结构体(Struct)-《Go语言实战指南》

结构体&#xff08;struct&#xff09;是 Go 中的一种复合数据类型&#xff0c;它允许你将多个不同类型的字段组合成一个类型&#xff0c;类似于 C 语言的结构体或面向对象语言中的类。 一、结构体的基本定义 type 结构体名 struct {字段名 字段类型... } 示例&#xff1a; …...

mediapipe标注视频姿态关键点(基础版加进阶版)

前言 手语视频流的识别有两种大的分类&#xff0c;一种是直接将视频输入进网络&#xff0c;一种是识别了关键点之后再进入网络。所以这篇文章我就要来讲讲如何用mediapipe对手语视频进行关键点标注。 代码 需要直接使用代码的&#xff0c;我就放这里了。环境自己配置一下吧&…...

PCtoLCD2002如何制作6*8字符

如何不把“等比缩放”前的打勾取消&#xff0c;则无法修改为对应英文字符为6*8。 取消之后就可以更改了&#xff01;...

SmartPlayer与VLC播放RTMP:深度对比分析延迟、稳定性与功能

随着音视频直播技术的发展&#xff0c;RTMP&#xff08;实时消息传输协议&#xff09;成为了广泛应用于实时直播、在线教育、视频会议等领域的重要协议。为了确保优质的观看体验&#xff0c;RTMP播放器的选择至关重要。大牛直播SDK的SmartPlayer和VLC都是在行业中广受欢迎的播放…...

Qt QPaintEvent绘图事件painter使用指南

绘制需在paintEvent函数中实现 用图片形象理解 如果加了刷子再用笔就相当于用笔画过的区域用刷子走 防雷达&#xff1a; 源文件 #include "widget.h" #include "ui_widget.h" #include <QDebug> #include <QPainter> Widget::Widget(QWidget…...

伪创新-《软件方法》全流程引领AI-第1章 04

《软件方法》全流程引领AI-第1章 ABCD工作流-01 对PlantUML们的评价-《软件方法》全流程引领AI-第1章 02 AI辅助的建模步骤-《软件方法》全流程引领AI-第1章 03 第1章 ABCD工作流 1.5 警惕和揭秘伪创新 初中数学里要学习全等三角形、相似三角形、SSS、SAS……&#xff0c;到…...

win11如何重启

在 Windows 11 中重启电脑有多种方法&#xff0c;以下是其中几种常见方法&#xff1a; 开始菜单重启&#xff1a; 点击屏幕左下角的“开始”按钮&#xff08;Windows 图标&#xff09;。 在开始菜单中&#xff0c;点击“电源”图标。 选择“重启”选项。 使用快捷键&#xf…...

【iOS】 锁

iOS 锁 文章目录 iOS 锁前言线程安全锁互斥锁pthread_mutexsynchronized (互斥递归锁)synchronized问题:小结 NSLockNSRecursiveLockNSConditionNSConditionLock 自旋锁OSSpinLock(已弃用)atomicatomic修饰的属性绝对安全吗?os_unfair_lock 读写锁互斥锁和自旋锁的对比 小结使…...

uni-app学习笔记十五-vue3页面生命周期(一)

页面生命周期概览 vue3页面生命周期如下图所示&#xff1a; onLoad 此时页面还未显示&#xff0c;没有开始进入的转场动画&#xff0c;页面dom还不存在。 所以这里不能直接操作dom&#xff08;可以修改data&#xff0c;因为vue框架会等待dom准备后再更新界面&#xff09;&am…...