Qt 学习之路 2(41):model/view 架构
Qt 学习之路 2(41):model/view 架构
有时,我们的系统需要显示大量数据,比如从数据库中读取数据,以自己的方式显示在自己的应用程序的界面中。早期的 Qt 要实现这个功能,需要定义一个组件,在这个组件中保存一个数据对象,比如一个列表。我们对这个列表进行查找、插入等的操作,或者把修改的地方写回,然后刷新组件进行显示。这个思路很简单,也很清晰,但是对于大型程序,这种设计就显得苍白无力。比如,在一个大型系统中,你的数据可能很大,全部存入一个组件的数据对象中,效率会很低,并且这样的设计也很难在不同组件之间共享数据。如果你要几个组件共享一个数据对象,要么你就要用存取函数公开这个数据对象,要么你就必须把这个数据对象放进不同的组件分别进行维护。
Smalltalk 语言发明了一种崭新的实现,用来解决这个问题,这就是著名的 MVC 模型。对这个模型无需多言。MVC 是 Model-View-Controller 的简写,即模型-视图-控制器。在 MVC 中,模型负责获取需要显示的数据,并且存储这些数据的修改。每种数据类型都有它自己对应的模型,但是这些模型提供一个相同的 API,用于隐藏内部实现。视图用于将模型数据显示给用户。对于数量很大的数据,或许只显示一小部分,这样就能很好的提高性能。控制器是模型和视图之间的媒介,将用户的动作解析成对数据的操作,比如查找数据或者修改数据,然后转发给模型执行,最后再将模型中需要被显示的数据直接转发给视图进行显示。MVC 的核心思想是分层,不同的层应用不同的功能。
Qt 4 开始,引入了类似的 model/view 架构来处理数据和面向最终用户的显示之间的关系。当 MVC 的 V 和 C 结合在一起,我们就得到了 model/view 架构。这种架构依然将数据和界面分离,但是框架更为简单。同样,这种架构也允许使用不同界面显示同一数据,也能够在不改变数据的情况下添加新的显示界面。为了处理用户输入,我们还引入了委托(delegate)。引入委托的好处是,我们能够自定义数据项的渲染和编辑。
![](http://files.devbean.net/images/2013/01/model-view-overview.png)
Model View 概览
如上图所示,模型与数据源进行交互,为框架中其它组件提供接口。这种交互的本质在于数据源的类型以及模型的实现方式。视图从模型获取模型索引,这种索引就是数据项的引用。通过将这个模型索引反向传给模型,视图又可以从数据源获取数据。在标准视图中,委托渲染数据项;在需要编辑数据时,委托使用直接模型索引直接与模型进行交互。
总的来说,model/view 架构将传统的 MV 模型分为三部分:模型、视图和委托。每一个组件都由一个抽象类定义,这个抽象类提供了基本的公共接口以及一些默认实现。模型、视图和委托则使用信号槽进行交互:
- 来自模型的信号通知视图,其底层维护的数据发生了改变;
- 来自视图的信号提供了有关用户与界面进行交互的信息;
- 来自委托的信号在用户编辑数据项时使用,用于告知模型和视图编辑器的状态。
所有的模型都是QAbstractItemModel
的子类。这个类定义了供视图和委托访问数据的接口。模型并不存储数据本身。这意味着,你可以将数据存储在一个数据结构中、另外的类中、文件中、数据库中,或者其他你所能想到的东西中。我们将在后面再详细讨论这些内容。
QAbstractItemModel
提供的接口足够灵活,足以应付以表格、列表和树的形式显示的数据。但是,如果你需要为列表或者表格设计另外的模型,直接继承QAbstractListModel
和QAbstractTableModel
类可能更好一些,因为这两个类已经实现了很多通用函数。关于这部分内容,我们也会在后文中详述。
Qt 内置了许多标准模型:
QStringListModel
:存储简单的字符串列表。QStandardItemModel
:可以用于树结构的存储,提供了层次数据。QFileSystemModel
:本地系统的文件和目录信息。QSqlQueryModel
、QSqlTableModel
和QSqlRelationalTableModel
:存取数据库数据。
正如上面所说,如果这些标准模型不能满足你的需要,就必须继承QAbstractItemModel
、QAbstractListModel
或者QAbstractTableModel
,创建自己的模型类。
Qt 还提供了一系列预定义好的视图:QListView
用于显示列表,QTableView
用于显示表格,QTreeView
用于显示层次数据。这些类都是QAbstractItemView
的子类。这意味着,如果你要创建新的视图类,则可以继承QAbstractItemView
。
则是所有委托的抽象基类。自 Qt 4.4 依赖,默认的委托实现是
QAbstractItemDelegateQStyledItemDelegate
。但是,QStyledItemDelegate
和QItemDelegate
都可以作为视图的编辑器,二者的区别在于,QStyledItemDelegate
使用当前样式进行绘制。在实现自定义委托时,推荐使用QStyledItemDelegate
作为基类,或者结合 Qt style sheets。
如果你觉得 model/view 模型过于复杂,或者有很多功能是用不到的,Qt 还有一系列方便使用的类。这些类都是继承自标准的视图类,并且继承了标准模型。这些类并不是为其他类继承而准备的,只是为了使用方便。它们包括QListWidget
、QTreeWidget
和QTableWidget
。这些类远不如视图类灵活,不能使用另外的模型,因此只适用于简单的情形。
Qt 学习之路 2(41):model/view 架构的更多相关文章
- Qt学习之路(45): 自定义model之一
前面我们说了Qt提供的几个预定义model.但是,面对变化万千的需求,那几个model是远远不能满足我们的需要的.另外,对于Qt这种框架来说,model的选择首先要能满足绝大多数功能的需要,这就是说, ...
- Qt学习之路:自定义Model三篇,自定义委托等等
http://devbean.blog.51cto.com/448512/d-8/p-2
- Qt 学习之路 2(31):贪吃蛇游戏(1)
Qt 学习之路 2(31):贪吃蛇游戏(1) 豆子 2012年12月18日 Qt 学习之路 2 41条评论 经过前面一段时间的学习,我们已经了解到有关 Qt 相当多的知识.现在,我们将把前面所讲过的知 ...
- Qt 学习之路 2(30):Graphics View Framework
Qt 学习之路 2(30):Graphics View Framework 豆子 2012年12月11日 Qt 学习之路 2 27条评论 Graphics View 提供了一种接口,用于管理大量自定义 ...
- 第15.23节 PyQt(Python+Qt)入门学习:Model/View架构中QListView视图配套Model的开发使用
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.概述 QListView理论上可以和所有QAbstractItemModel派生的类如QStri ...
- 第15.22节 PyQt(Python+Qt)入门学习:Model/View架构详解
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 一.简介 在PyQt和Qt中,Model/View架构是图形界面开发时用于管理数据和界面展现方式的关 ...
- 第15.18节 PyQt(Python+Qt)入门学习:Model/View架构中视图Item Views父类详解
老猿Python博文目录 老猿Python博客地址 一.概述 在PyQt图形界面中,支持采用Model/View架构实现数据和界面逻辑分离,其中Model用于处理数据存储,View用于界面数据展现,当 ...
- PyQt(Python+Qt)学习随笔:model/view架构中类QStandardItemModel的使用方法
老猿Python博文目录 老猿Python博客地址 一.概述 QStandardItemModel是QAbstractItemModel的派生类,用于在Model/View架构中存储自定义数据的通用模 ...
- PyQt(Python+Qt)学习随笔:Model/View架构中的Model模型概念
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 Model/View架构中的Model模型Model与数据源通信,为体系结构中的其他组件提供数据接口 ...
随机推荐
- Javamail简单使用案例
邮件开发环境搭建 邮件服务器 易邮邮件服务器 配置如下 邮件客户端 Foxmail 配置如下 使用Javamail发送邮件 下载 javamail-samples.zip javax.mail.jar ...
- ubuntu 编译并安装resin3.1.12+nginx1.2.6
一.先装jdk 先建立如下两个目录: mkdir /usr/lib/jvm mkdir /usr/lib/jvm/java 把jdk-6u26-linux-x64.bin文件传到上面目录下: chmo ...
- Codeforces 1109C 线段树
题意及思路:https://www.cnblogs.com/TinyWong/p/10400682.html 代码: #include <bits/stdc++.h> #define ls ...
- qt数据库有效插件为空的情况
打了一周的环境,从ubuntu到win7,搭建环境的时间比写代码的时间都多.先简单的介绍一下我搭建的环境不是纯QT环境,是一个芬兰的软件开发商开发出来的SDK里面完全融合qt,其中qt是以单独的目录存 ...
- sudo apt install libreadline-dev Reading package lists... Error!
luo@luo-ThinkPad-W540:~$ luo@luo-ThinkPad-W540:~$ luo@luo-ThinkPad-W540:~$ luo@luo-ThinkPad-W540:~$ ...
- 1-element.src.match("bulbon")
element.src.match("bulbon")这里的math里面”bulbon“是什么意思? 原代码中 if (element.src.match("bulbon ...
- 使用pycharm运行调试scrapy
摘要 Scrapy是爬虫抓取框架,Pycharm是强大的python的IDE,为了方便使用需要在PyCharm对scrapy程序进行调试 python PyCharm Scrapy scrapy指令其 ...
- Logistic Regression 用于预测马是否生病
1.利用Logistic regression 进行分类的主要思想 根据现有数据对分类边界线建立回归公式,即寻找最佳拟合参数集,然后进行分类. 2.利用梯度下降找出最佳拟合参数 3.代码实现 # -* ...
- oracle数据库基本操作
我们主要学习数据库的一些基本操作,比如如何在数据库创建用户,授权,删除用户,回收权限,为用户加锁或者解锁等一些常用的操作. 首先,我们要知道数据库中创建用户的语句怎么写,看下面: 1.创建用户 cre ...
- 无法解析的外部符号 _WinMain@16(原)
原来的控制台程序,想修改为windows程序时,会出现 无法解析的外部符号 WinMain,该符号在函数 __tmainCRTStartup 中被引用 在链接器->高级->入口点输入:ma ...