Qt 模型/视图/委托
模型、视图、委托
模型/视图架构基于MVC设计模式发展而来。MVC中,模型(Model)用来表示数据;视图(View)是界面,用来显示数据;控制(Controller)定义界面对用户输入的反应方式。
Qt中视图和控制结合在一起形成新的模型/视图架构。这同样将数据的存储和数据向用户展示进行了分离,但提供了更为简单的框架。数据和界面分离,使得相同的数据可以在不同的视图显示,而且可以扩展新的视图,而不需要改变底层的数据框架。为了灵活处理用户输入,引入了委托,也称为代理,使用它可以定制数据的渲染和编辑方式。
模型与数据通信,为其它组件提供接口。视图通过模型索引(Model Index)从模型中获取数据,模型索引用来表示数据项。委托渲染数据项,编辑项目时,委托使用模型索引直接与模型通信。
它们之间的关系为:
(1).当数据源发生变化时,模型发出信号通知视图。
(2).用户对界面进行操作时,视图发出信号提供交互信息。
(3).用户编辑数据时,代理发出信号告知模型和视图编辑器的状态。
1. 模型
模型用来提供数据,并提供了一个标准的接口供视图和委托来访问数据。这个接口由QAbstractItemModel类来定义,不管数据项是什么结构,它都会以层次结构来表示数据,这个结构中包含了数据项表。视图按照这种约定来访问模型中的数据,但这不会影响数据的显示,视图可以使用任何形式将数据显示出来。当数据发生变化时,模型会通过信号和槽机制通知关联的视图。
(1) 模型索引 QModelIndex
模型索引使数据的表示与数据的获取相分离,每一块可以获取的数据都用一个模型索引来表示,视图和委托使用模型索引来请求数据项并显示。
模型索引包含一个模型指针,指向创建它们的模型,使用多个模型时可以避免出错。
由于模型中的数据在随时变化,因此模型引随时会变化,不需要也不应当保存一个模型索引,如果需要长时间引用一块数据,则必须使用QPersistentModelIndex创建模型索引。
QAbstractItemModel类中提供了 index接口获取模型索引,QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()),通常可将数据看成是一个表格结构,提供行和列的索引,对于树形结构,则提供其父索引。
(2) 数据项 QStandardItem
模型中的数据项可以作为各种角色在其它组件中使用,允许为其它组件提供不同类型的数据。通过为每个角色提供合适的数据,模型可以告知视图和委托如何显示数据。
Qt::DisplayRole |
数据为QString类型,渲染为文本 |
Qt::DecorationRole |
数据被渲染为图标等装饰,类型通常为QColor,QIcon,QPixmap等 |
Qt::EditRole |
数据为QString类型,可在编辑器中编辑 |
Qt::ToolTipRole |
数据为QString类型,显示在工具提示中 |
Qt::StatusTipRole |
数据为QString类型,显示在状态栏 |
Qt::WhatThisRole |
数据为QString类型,显示在“What’s This?”模式下 |
Qt::SizeHintRole |
数据类型为QSize,表示数据项的大小,将会应用到视图 |
(3) QAbstractItemModel 提供了灵活的接口,可以将数据表示为列表、表格、数等形式。其子类 QAbstractListModel 和 QAbstractTableModel 为列表和表格结构的数据提供了一些常见的默认实现。
Qt定义了许多默认的模型实现,在应用中可以直接拿来使用。
QStandardItemModel:一个可被当作表模型、表格模型、数模型使用的通用模型,可用来管理复杂的树型结构树据,每一个数据项都可以包含任意数据。但它有个缺点:加载大数据时较慢。
QStringListModel:用来存储一个简单的QString项目的列表模型。
QFileSystemModel:提供本地文件系统中的文件和目录信息。
QSqlQueryModel:访问数据库。
(4) 自定义模型
当要为一个已经存在的数据结构创建一个新的模型时,需要考虑使用哪种类型的模型来为数据提供接口,如果数据结构可以表示为项目列表或表格,则可以考虑子类化QAbstractListModel 和 QAbstractTableModel来实现。
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; // 为不同角色提供数据
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); // 设置对应模型索引下的数据
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; // 表头数据
Qt::ItemFlags flags(const QModelIndex &index) const; // 返回模型索引是否可编辑,是否可用,编辑,选择等等状态
int rowCount(const QModelIndex &parent = QModelIndex()) const; // 当前父索引下的行数
int columnCount(const QModelIndex &parent = QModelIndex()) const; // 当前父索引下的列数
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()); // 添加行 添加前需要调用 beginInsertRows,添加完成后调用 endInsertRows
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()); // 删除行 删除前需要调用 beginRemoveRows,删除完成后调用 endRemoveRows
2. 视图
视图用来显示数据。
视图中的标准接口由 QAbstractItemView 类提供。
视图通常管理从模型获取的数据的整体布局,它们可以自己渲染独立的数据项,也可以使用委托来渲染和编辑。
除了呈现数据,视图还处理项目间的导航以及项目选择的某些方面,如设置选择行为 SelectionBehavior、选择模式SelectionMode,上下文菜单和拖放等。
(1) QItemSelectionModel 选择模型
这里的选择模型和前面的模型是不同的概念,在视图中被选择项目的信息都存储在 QItemSelectionModel 实例中,这样被选择项目的模型索引便保持在一个独立的模型中,与所有的视图都是独立的。在一个模型上设置多个视图时就可以实现多个视图共享。QItemSelectionModel 对象可以通过视图的接口获取和重新设置。
QItemSelectionModel *selectionModel() const;
void setSelectionModel(QItemSelectionModel *selectionModel);
QItemSelectionModel 对象会保存当前模型的指针,也可以返回操作的模型索引列表。
QModelIndexList selectedIndexes() const;
(2) Qt提供了几种常用的视图,都是使用规范的格示来显示数据,如果还要实现条形图、饼状图或更复杂的图形,就要重新实现视图类。
QListView: 将数据显示为一个列表。
QTableView: 将模型中的数据显示在一个表格中。
QTreeView: 将模型中的数据项显示在具有层次的列表中。
QColumnView: 提供一个多级视图(每点开一选项都会在它旁边出现一个菜单)。
3.委托
委托提供特殊显示和编辑功能。委托的标准接口由 QAbstractItemDelegate 类提供。委托通过 paint() 和 sizeHint() 函数来使它们可以渲染自身的内容。
委托的编辑功能可以通过两种方式来实现,一种是使用部件来管理编辑过程,另一种是直接处理事件(通过子类化输入控件完成)。
QItemDelegate 和QStyledItemDelegate 是委托Qt提供的两种委托实现。
QStyledItemDelegate使用当前的样式来绘制项目,当要自定义的委托要使用样式表一起应用时,建议使用它作为基类。
QListView、QTableView和QTreeView都使用QItemDelegate来提供编辑功能,这使得它们只有普通风格的渲染。
视图可以获取和设置委托。
void setItemDelegate(QAbstractItemDelegate *delegate);
QAbstractItemDelegate *itemDelegate() const;
(1) 自定义委托示例
当视图需要编辑器时,它会告知委托为被修改的项目提供一个编辑器部件,委托会调用 createEditor 函数提供一个合适的部件。
在自定义委托时,createEditor返回一个可编辑输入的控件对象,如果不需要编辑,则返回 nullptr, 返回的指针对象不需要保存,因为视图在不需要的时候会销毁它。
setEditorData 函数将模型中的数据渲染到编辑器中。
setModelData 函数在用户完成了输入之后,将数据存储到模型中。
updateEditorGeometry 函数用来调整编辑器的位置和大小,QStyleOptionViewItem对象提供了几何布局相关的信息。
代理对象会在完成编辑后发射 closeEditor 信号来告知视图。
class SpinDelegate : public QItemDelegate
{
Q_OBJECT
public:
using QItemDelegate::QItemDelegate;
// 创建编辑器
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
// 为编辑器设置数据
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
// 将数据写入到模型
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
// 更新编辑器的几何布局
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
};
QWidget* SpinDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QSpinBox* editor = new QSpinBox{parent};
editor->setRange(0, 40);
return editor;
}
void SpinDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
QSpinBox* spinBox = dynamic_cast<QSpinBox*>(editor);
if (spinBox)
{
bool isOK = false;
int value = index.model()->data(index, Qt::EditRole).toInt(&isOK);
if (isOK)
{
spinBox->setValue(value);
}
}
}
void SpinDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
QSpinBox* spinBox = dynamic_cast<QSpinBox*>(editor);
if (spinBox)
{
spinBox->interpretText(); // 确保取得最新的数值
int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}
}
void SpinDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
editor->setGeometry(option.rect);
}
Qt 模型/视图/委托的更多相关文章
- PyQt5模型视图委托
Model-View-Delegate 模型视图委托(MVD)是PyQt中特有的设计模式,类似MVC设计模式,将MVC设计模式中的Controller当做MVD中的Delegate,两者的概念基本相同 ...
- Qt模型/视图框架----简单的例子
#include<qapplication.h> #include<qfilesystemmodel.h> #include<qtreeview.h> #inclu ...
- Qt模型/视图、委托
MVC视图和控制器对象相结合,其结果是模型/视图结构,仍然分离了数据与呈现给用户的方式,使得它可以在几个不同的视图中显示相同的数据,并实现新类型的视图而无需改变底层的数据结构.为了灵活的处理数据输入, ...
- 38.Qt模型/视图结构
1.模型/视图类 2.模型 3.视图 4.代理 1 模型/视图类 InterView框架提供了一些可以直接使用的模型类和视图类,如QStandardModel类,QDirModel类,QStringL ...
- Qt 模型/视图结构
MVC是一种与用户界面相关的设计模式.通过使用此模型,可以有效地分离数据和用户界面.MVC设计模式包含三要素:表示数据的模型(Model).表示用户界面的视图(View)和定义了用户在界面上的操作控制 ...
- Qt模型视图结构遇见的小问题
在本文的最开始,我们来看两个帮助文档内容: selectionMode : SelectionMode This property holds which selection mode the vie ...
- 【转】Qt之模型/视图
[本文转自]http://blog.sina.com.cn/s/blog_a6fb6cc90101hh20.html 作者: 一去丶二三里 关于Qt中MVC的介绍与使用,助手中有一节模型/视图编程 ...
- Qt之模型/视图(委托)
概念 不同于模型 - 视图 - 控制器模式,模型/视图设计不包括用于管理与用户交互的一个完全独立的组件.一般情况,视图负责将模型数据呈现给用户以及处理用户输入.为了输入更加具有灵活性,则由委托来执行交 ...
- Qt之模型/视图(自定义进度条)
简述 在之前的章节中分享过关于QHeaderView表头排序.添加复选框等内容,相信大家模型/视图.自定义风格有了一定的了解,下面我们来分享一个更常用的内容-自定义进度条. 实现方式: 从QAbstr ...
随机推荐
- Performance — 前端性能监控利器
Performance是一个做前端性能监控离不开的API,最好在页面完全加载完成之后再使用,因为很多值必须在页面完全加载之后才能得到.最简单的办法是在window.onload事件中读取各种数据. 大 ...
- CS小分队第二阶段冲刺站立会议(6月3日)
昨日成果:完成了主界面按钮移动交换位置 遇到问题:最后的时候发现仅交换了按钮在数据库中的信息,对于按钮的链接忘记交换了 今日计划:解决这个问题,对这个冲刺阶段的成果进行整理
- 第二阶段Sprint2
昨天:讨论冲刺阶段,目标,任务认领 今天:查看资料,开始视频录制部分的代码实现 遇到的问题:不能暂停后继续录制,只能直接结束
- 2018软工实践—Beta冲刺(2)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Beta 冲鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调组内工作 修改前端界面 展示GitHub当日代码/文档签入记录(组内 ...
- ubuntu下安装matlab2015b
========= 安装过程 1.下载MATLAB2015b破解版 操作系统:Ubuntu 16.04 LTS 程序文件:Matlab2015b-glnxa64破解版 解压提取文件:在ubuntu系统 ...
- HDU 4026 Unlock the Cell Phone 状压dp(类似TSP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4026 Unlock the Cell Phone Time Limit: 6000/3000 MS ...
- 网络1711-12&信管1711-12 图 作业评分
先放上本次作业的推荐博客,以及评分细则总表,在最后,会放几张图表对本学期大家的成果进行一个小小的总结,有兴趣的同学可以看看,感受一下自己这个学期的积累和进步.(主要针对网络的同学,信管的同学只有两次作 ...
- android自动化之appium的环境搭建
简介appium appium是C/S架构,appium的核心是一个web服务器,它提供了一套REST的接口,他会接收客户端的连接,监听到命令.执行会再将结果通过HTTP响应返还给客户端.ap ...
- 原生Ajax函数
前言 在日常工作中,我经常使用Jquery的Ajax来获取接口数据.这几天有一个的官网要制作,由于网站比较小,有一些与服务器通信的接口处理,并没有涉及到复杂的交互功能.为了可以减少加载Jquery库的 ...
- UVAlive4080_Warfare And Logistics
给一个无向图,求出两个值,所有点到所有其他点的最短距离和,任意删除一条边后的这个值. 数据规模是100点1000边. 白书例题,不多说了直接对于每个点求出最短路树,对于每条边,如果它不是最短路树上的边 ...