QT模型视图结构1
文章目录
- Qt 模型视图结构概述(一)
- 1、模型/视图结构基本原理
- 2、模型
- 3、视图
- 4、代理
- 5、简单实例
Qt 模型视图结构概述(一)
模型/视图结构是一种将数据存储和界面展示分离的编程方法。模型存储数据,视图组件显示模型中的数据,在视图组件里修改的数据会被自动保存到模型里。模型的数据来源可以是内存中的字符串列表或二维表格型数据,也可以是数据库中的数据表,一种模型可以用不同的视图组件来显示数据,所以模型/视图结构是一种高效、灵活的编程结构。
1、模型/视图结构基本原理
GUI 程序的主要功能是可由用户在界面上编辑和修改数据,典型的如数据库应用程序。在数据库应用程序中,界面上的数据来源于数据库,用户在界面上修改数据,修改后的数据又保存到数据库。
将界面与原始数据分离,又通过模型将界面和原始数据关联起来,从而实现界面与原始数据的交互操作,这是处理界面与数据的一种较好的方式。
Qt 使用模型/视图结构来处理这种关系,模型/视图的基本结构如图 1 所示,它包括以下几个部分。

| 图 1 模型/视图基本结构 |
|---|
- 源数据(data)是原始数据,如数据库的一个数据表或
SQL查询结果、内存中的一个字符串列表或磁盘文件系统结构等。 - 视图(view)也称为视图组件,是界面组件,视图从模型获得数据然后将其显示在界面上。Qt 提供一些常用的视图组件,如
QListView、QTreeView和QTableView等。 - 模型(model)也称为数据模型,与源数据通信,并为视图组件提供数据接口。它从源数据提取需要的数据,用于视图组件进行显示和编辑。Qt 中有一些预定义的模型类,如
QStringListModel是字符串列表的模型类,QSqlTableModel是数据库中数据表的模型类。 - 代理(delegate)在视图与模型之间交互操作时提供的临时编辑器。模型向视图提供数据是单向的,一般仅用于显示。当需要在视图上编辑数据时,代理会为编辑数据提供一个编辑器,这个编辑器获取模型的数据、接受用户编辑的数据后又将其提交给模型。例如在
QTableView组件上双击一个单元格来编辑数据时,在单元格里就会出现一个QLineEdit组件,这个编辑框就是代理提供的临时编辑器。
由于通过模型/视图结构将源数据与显示和编辑界面分离,我们可以将一个模型在不同的视图中显示,也可以为一些特殊源数据设计自定义模型,或者在不修改模型的情况下设计特殊的视图组件。所以,模型/视图结构是一种高效、灵活的编程结构。
模型、视图和代理使用信号和槽进行通信。当源数据发生变化时,模型发射信号通知视图组件;当用户在界面上操作数据时,视图组件发射信号表示操作信息;在编辑数据时,代理会发射信号告知模型和视图组件编辑器的状态。
2、模型
所有基于项(item)的模型类都是基于 QAbstractItemModel 类的,这个类定义了视图组件和代理存取数据的接口。模型只是在内存中临时存储数据,模型的数据来源可以是其他类、文件、数据库或任何数据源。
Qt 中几个主要的模型类的继承关系如图 2 所示。QAbstractItemModel 的父类是 QObject,所以模型类支持 Qt 的元对象系统。

| 图 2 模型类的继承关系 |
|---|
抽象模型类 QAbstractItemModel 不能直接用于创建实例对象,常用的几个模型类如表 1 所示。
| 表 1 常用的模型类 |
|---|
| 模型类 | 功能 |
|---|---|
QFileSystemModel | 用于表示计算机上文件系统的模型类 |
QStringListModel | 用于表示字符串列表数据的模型类 |
QStandardItemModel | 标准的基于项的模型类,每个项是一个 QStandardItem 对象 |
QSqlQueryModel | 用于表示数据库 SQL 查询结果的模型类 |
QSqlTableModel | 用于表示数据库的一个数据表的模型类 |
3、视图
视图就是用于显示模型中的数据的界面组件,Qt 提供的视图组件主要有以下几个。
| 表 2 常用的视图类 |
|---|
| 视图组件 | 用于显示单列的列表数据,适用于一维数据的操作 |
|---|---|
QListView | 用于显示单列的列表数据,适用于一维数据的操作 |
QTreeView | 用于显示树状结构数据,适用于树状结构数据的操作 |
QTableView | 用于显示表格数据,适用于二维表格数据的操作 |
QColumnView | 用多个 QListView 显示树状结构数据,树状结构的一层用一个QListView显示 |
QUndoView | 用于显示 undo 指令栈内数据的视图组件,是 QListView 的子类 |
QListWidget、QTreeWidget 和 QTableWidget 这 3 个用于处理项数据的组件。这3 个类分别是 3 个视图类的子类,称为视图类的便利类(convenience class)。这些类的继承关系如图 3 所示。

| 图 3 视图类的继承关系 |
|---|
只需调用视图类的 setModel()函数为视图组件设置一个模型,模型的数据就可以显示在视图组件上。在视图组件上修改数据后,数据可以自动保存到模型里。视图组件的数据来源于模型,视图组件不存储数据。便利类则为组件的每个节点或单元格创建一个项,用项存储数据,例如对于 QTableWidget 类这个便利类,表格的每个单元格关联一个QTableWidgetItem 对象。便利类没有模型,它实际上是用项的方式替代了模型的功能,将界面与数据绑定。因此,便利类缺乏对大型数据源进行灵活处理的能力,只适用于小型数据的显示和编辑,而视图组件则会根据模型的数据内容自动显示,有助于减少编程工作量,使用起来也更灵活。
4、代理
代理就是在视图组件上为编辑数据提供的临时编辑器,例如在 QTableView 组件上编辑一个单元格的数据时,默认会提供一个 QLineEdit 编辑框。代理负责从模型获取相应的数据,然后将其显示在编辑器里,修改数据后又将编辑器里的数据保存到模型中。
QAbstractItemDelegate 是所有代理类的基类。它有两个子类, QItemDelegate 和QStyledItemDelegate ,这两个类的功能基本相同,而QStyledItemDelegate 能使用 Qt 样式表定义的当前样式绘制代理组件,所以,QStyledItemDelegate是视图组件使用的默认的代理类。
对于一些特殊的数据编辑需求,例如只允许输入整数时使用 QSpinBox 作为代理组件更合适,需要从列表中选择数据时则使用 QComboBox作为代理组件更好,这时就可以从 QStyledItemDelegate继承创建自定义代理类。
5、简单实例
展示了模型/视图类使用的简单实例 main.cpp
#include <QApplication>
#include <QSplitter>
#include <QFileSystemModel>
#include <QTreeView>
#include <QListView>int main(int argc, char *argv[])
{QApplication app(argc, argv);QSplitter *splitter = new QSplitter;QFileSystemModel *model = new QFileSystemModel;model->setRootPath(QDir::currentPath());QTreeView *tree = new QTreeView(splitter);tree->setModel(model);tree->setRootIndex(model->index(QDir::currentPath()));QListView *list = new QListView(splitter);list->setModel(model);list->setRootIndex(model->index(QDir::currentPath()));splitter->setWindowTitle("Two views onto the same file system model");splitter->show();return app.exec();
}
实例运行展示如下图

相关文章:
QT模型视图结构1
文章目录 Qt 模型视图结构概述(一)1、模型/视图结构基本原理2、模型3、视图4、代理5、简单实例 Qt 模型视图结构概述(一) 模型/视图结构是一种将数据存储和界面展示分离的编程方法。模型存储数据,视图组件显示模型中的数据,在视图组件里修改的数据会…...
Ubuntu20+Noetic+cartographer_ros编译部署
1 准备工作 (1)准备Ubuntu20系统。 (2)安装ROS系统,参考 https://blog.csdn.net/weixin_46123033/article/details/139527141(3)Cartographer相关软件包和源码下载: https://gitee.com/mrwan…...
linux-L3-linux 复制文件
linux 中要将文件file1.txt复制到目录dir中,可以使用以下命令 cp file1.txt dir/复制文件 cp /path/to/source/file /path/to/destination移动 mv /path/to/source/file /path/to/destination复制文件夹内的文件 cp -a /path/to/source/file /path/to/destinati…...
Kotlin:1.9.0 的新特性
一、概述 Kotlin 1.9.0版本英语官方文档 Kotlin 1.9.0 中文官方文档 The Kotlin 1.9.0 release is out and the K2 compiler for the JVM is now in Beta. Additionally, here are some of the main highlights: Kotlin 1.9.0版本已经发布,用于JVM的K2编译器现在…...
golang实现从服务器下载文件到本地指定目录
一、连接服务器,采用sftp连接模式 package middlewaresimport ("fmt""time""github.com/pkg/sftp""golang.org/x/crypto/ssh" )// 建立服务器连接 func Connect(user, password, host string, port int) (*sftp.Client, e…...
C++数据结构-树的概念及分类介绍(基础篇)
1.什么是树 树是数据结构中的一种,其属于非线性数据结构结构的一种,我们前文所提到的数据结构多数都是线性的,这也是较为简单的数据结构,而接下来的树与图均属于非线性数据结构,也是概念极多的一类。 树是由结点或顶…...
职场 Death Note
场景一 测试:哎,怎么会这样呢?时间没到,他怎么就变成这个样子了呢?一副大惊小怪,整个办公室都是他的声音 开发:对对对,我代码问题,别BB了。 你直接说这个地方不对&#…...
Vue3.0组合式API:computed计算属性、watch监听器、watchEffect高级监听器
1、computed() 计算属性 在模板中绑定表达式只能用于简单的运算。如果运算比较复杂,可以使用 Vue.js 提供的计算属性,通过计算属性可以处理比较复杂的逻辑。 1.1 计算属性的应用 通过计算属性可以实现各种复杂的逻辑,包括运算、函数调用等…...
RAII 与 std::lock_guard 在 C++ 中的应用:自动化互斥锁管理与线程安全
目录 1. RAII(资源获取即初始化)概述 RAII 的优点 2. std::lock_guard 的工作原理 2.1 构造函数 2.2 析构函数 2.3 关键特性 3. 为什么 std::lock_guard 能自动管理锁的生命周期 3.1 RAII 原则的应用 3.2 异常安全 3.3 简化代码和减少错误 4.…...
风格汇:奢华风格在UI设计中如何被定义的。
在UI设计中,奢华风格通常指的是一种高端、豪华、精致的设计风格,旨在营造出奢华、豪华的视觉效果,给用户带来高品质、高档次的感受。 奢华风格的UI设计通常会运用一些富丽堂皇的元素和效果,例如金色、银色、贵族紫、华丽的字体、华…...
Vue2 qrcode+html2canvas 实现二维码的生成和保存
1.安装 npm install qrcode npm install html2canvas 2.引用 import QRCode from qrcode import html2canvas from html2canvas 效果: 1. 二维码生成: 下载二维码图片: 二维码的内容: 实现代码: <template>…...
GEE 教程:利用Google Dynamic数据进行逐月指定区域的土地分类数据提取分析
目录 简介 数据 代码 结果 简介 利用Google Dynamic数据进行逐月指定区域的土地分类数据提取分析 数据 Google Dynamic数据是指由Google自动生成、自动更新的数据,它不需要人工干预,而是通过算法和机器学习技术从各种来源获取并解析数据。这些数据可以是来自互联网上的…...
Nginx 负载均衡:优化网站性能与可扩展性的利器
在当今高流量的互联网时代,网站的性能和可扩展性成为了衡量其成功与否的关键因素之一。随着用户量的不断增加,单一服务器往往难以承受巨大的访问压力,这时就需要引入负载均衡技术来分散请求,提高系统的整体性能和可靠性。Nginx&am…...
【Python基础】Python错误和异常处理(详细实例)
本文收录于 《Python编程入门》专栏,从零基础开始,分享一些Python编程基础知识,欢迎关注,谢谢! 文章目录 一、前言二、Python中的错误类型三、Python异常处理机制3.1 try-except语句3.2 try-except-else语句3.3 try-fi…...
如何查看串口被哪个程序占用?截止目前最方便的方法
痛点:串口因为某种原因被占用,如何找到罪魁祸首? 做开发的小伙伴们,经常会遇到这样的问题:串口因为某种原因被占用,导致无法通讯,但是又找不到被哪个程序占用。只有重启电脑,才能解…...
深入理解SpringBoot(一)----SpringBoot的启动流程分析
1、SpringApplication 对象实例化 SpringApplication 文件 public static ConfigurableApplicationContext run(Object[] sources, String[] args) {// 传递的source其实就是类Bootstrapreturn new SpringApplication(sources).run(args);// 实例化一个SpringApplication对象执…...
MySql基础-单表操作
1. MYSQL概述 1.1 数据模型 关系型数据库 关系型数据库(RDBMS):建立在关系模型基础上,由多张相互连接的二维表组成的数据库。 特点: 使用表存储数据,格式统一,便于维护 使用SQL语言操作,标准统一&…...
【STM32系统】基于STM32设计的SD卡数据读取与上位机显示系统(SDIO接口驱动、雷龙SD卡)——文末资料下载
基于STM32设计的SD卡数据读取与上位机显示系统 演示视频: 基于STM32设计的SD卡数据读取与上位机显示系统 简介:本研究的主要目的是基于STM32F103微控制器,设计一个能够读取SD卡数据并显示到上位机的系统。SD卡的数据扇区读取不仅是为了验证存…...
SpringBoot开发——整合Redis
文章目录 1、创建项目,添加Redis依赖2、创建实体类Student3、创建Controller4、配置application.yml5、整合完成 Redis ( Remote Dictionary Server )是一个开源的内存数据库,遵守 BSD 协议,它提供了一个高性能的键值(…...
OpenCV结构分析与形状描述符(17)判断轮廓是否为凸多边形的函数isContourConvex()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 测试轮廓的凸性。 该函数测试输入的轮廓是否为凸的。轮廓必须是简单的,即没有自相交。否则,函数的输出是不确定的。 cv:…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
JavaScript基础-API 和 Web API
在学习JavaScript的过程中,理解API(应用程序接口)和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能,使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...
力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
