Model/View模型视图

version

model

在这里插入图片描述
model 就是一个 数据结构,形如上图。

他一定必有的是: 一个root, 指向一个 主table
这个主table,有一个headers(即标签,比如你可以自定义为:姓名,年龄、、、)

这1个root 和 主table的n*m个cell,官方称为: item 一个项
可以发现,一个项 其实是个指针,他可以指向一个 子表table


即,model这个数据结构,他是一种 递归的结构,因为每一个item(cell),他都是一个指针,链接一个新table

因为每一个cell,都是一个指针,可以无限拓展。
为了方便管理,每个model 都是1个root 来统一管理(和链表的根指针 思想一样)
我们形象的说,这个结构是model,其实 并不存在model这个定义,qt里只有:itemModel

这就和链表list一样,list里没有存储所有节点的指针,或者说 并没有list这个东西。
我们只是拿到了一个链表指针head,然后不停的走next,遍历整个链表。
即,并不存在list这个结构体定义,我们只是对list里的每个节点node,定义node的结构体!!!

同样model也是完全一样的,没有对model的结构体定义。
只是对model里的每一个cell,有对cell的结构体定义。
这样,根据cell的next指针,来遍历整个model

这个cell,在qt里称为:QAbstractItemModel,qt里并没有QAbstractModel
即使是一些qt写好的现成model,比如:QFileSystemModel、、、 虽然名字里没有item,看似他是一个model
但其实不是的!,他也是继承自QAbstractItemModel


这是他的存储结构。 可以发现,这个存储结构,他几乎可以表示出,任何你能想到的数据结构。

比如,常用的list、table、tree,都可以表示出来。
在这里插入图片描述


这是他的存储结构。 我们不仅要存储,还要用来使用 即索引retrieve。

每一个item(cell) 他里面存储的 只有数据,而为了定位 每一个item的位置 因为model结构很复杂,位置定位即为重要

qt为每一个item,都配备了一个名为index的数据结构 QModelIndex(他是单独的类,没有父类)

QModelIndex里有int row, int column, QModelIndex parent
表示当前这个index, 相对他所在的table里的行号和列号,parent表示该table的 父index。
没有child,因为一个index 也就是一个cell,他的儿子 是一个table,而不是一个cell!!!
所以,不会通过index来获取他的子表。 具体方式下面会介绍。
总之,index存储: 当前这个cell,在当前子表table的位置,以及父index


因此,一个cur_index,就是来指定一个cell。
一个cur_index,他里面的内容是: row, column, Parent
Parent是一个index,他指向了一个table。这个table的[row, column],就是cur_index

可以发现,我们没有办法指定root 这个index,因为他没有parent!!!
所以,qt规定,root这个index 你可以直接构造出来。他就是QModelIndex()

其他的index,不能直接构造出来。因为需要获取他的父index


他有个函数data(),表示当前cell里的数据。
但注意, index里没有data这个变量,index只存储位置信息。
data是一个功能函数,他会找到: 该index所引用的cell里的data,即他的找的item里的数据

即,我们先要拿到index对象 精确定位到哪一个cell之后,去获取该位置上的cell

虽然我们使用的数据 就是这个主table,以及他的儿子们,但是 model会自动给我们加一个root

也就是,一个model = 1个root + 我们的table
我们要获取我们的table,肯定要先获取root!!! 因为root是tabel的父指针。 就和list一样,必须要先得到head指针

qt中规定,每一个model 的 root,他的定位,都为:QModelIndex(),即一个空的index对象。

每个model里,一个空的index对象,就表示root这个cell

我们得到root后,就可以往下遍历 我们table里的cell


我们一般认为,model里每个cell存储的数据 就是纯数据。 比如db里的数据。

但在qt里,他的范围更广。 从而让ui存储的数据 几乎没有!!

比如,你的一个cell 对应到ui的一个cell。
ui的一个cell,他里面不仅有data,还有: 字体颜色,背景颜色,文本对齐方式,, 很多ui的属性。

这在model里, model的cell 也是要存储这些信息的!!!

即一个cell,他里面存储的 不仅只有data,还有很多附加信息(字体颜色…)

即,一个cell里的数据,是分类的,在qt中称为role

你去获取一个cell的数据:itemData(index) 根据定位 获取一个cell的数据。 他的返回值是:QMap<int, QVariant>
其中,QVariant自然是cell里存储的数据, 这个int 便是类型

qt里有定义enum:

namespace Qt{
   
	enum ItemDataRole{
   
		DisplayRole  ' 显示的文本 '
        FontRole  ' 字体格式 '
        TextAlignmentRole  ' 对齐方式 '
        BackgroundRole  ' 背景颜色 '
        ForegroundRole  ' 前景颜色 '
        、、、
	}
}

一般,我们不直接操作item。 因为item里的数据,是分类的。我们要操作的 是某一个role

所以,qt封装了函数,供我们方便使用:
setData(index, value, role)
QVariant data(index, role)


函数

实际使用时,我们并不是直接得到root,然后每次我们自己写函数来移动指针 定位到某个cell,这也太麻烦了…

qt给我们封装了,就叫做: QAbstractItemModel
setHeaderData(第几个, 方向, 数据, role) 设置表头信息
headerData(第几个, 方向, role) 获取表头信息
注意,header表头 他也是item!!! 即他也分role
但root并不指向header!!root指向主表 主表里都是数据
所以, 一个model,并不只是一个root 他里面还有header,是对整个模型的封装

int rowCount(index) 获取index 他指向的子表的行数!!
int columnCount(index) 获取index 他指向的子表的列数!!

QModelIndex index(row, column, QModelIndex parent) parent他指向了一个table表,获取这个table表的[row, column]这个cell
QVariant data(index, role) index所代表的cell里的数据(等价于:index.data(role)
bool setData(index, value, role) 设置index所代表的cell里的数据

遍历

给你一个model XX_model model; 且XX_model 是QAbstractModel的子类,请你遍历这个model里的所有文本数据
因为一个cell里有很多cell,只遍历文本数据 DisplayRole

void dfs(const XX_model& model, QModelIndex parent){
   
    DE<< model.data(parent, Qt::DisplayRole).toString();

    int rows = model.rowCount(parent); ' parent所指向的子表 '
    int columns = model.columnCount(parent);
    FOR(i, 0, rows-1, 1){
   
        FOR(j, 0, columns-1, 1){
   
            dfs(model, model.index(i, j, parent));
        }
    }
}

视图

当前项、选中项

一个视图,会一直有一个“当前项”,因为当键盘上下移动导航时,会需要这个项,所以他必须一直存在

当我们鼠标选中时,又会产生“选中项”。 一个项,可以同时是: 当前项 和 选中项

当前项 选中项
任何时刻,始终只有1个 可以有[0, inf]个
当键盘移动、鼠标点击时,当前项就会改变 鼠标单击、键盘ctrl/shift都可以选中。这要看selectionMode,可以自定义模式

Select

SelectionMode

void QAbstractView::setSelectionMode(QAbstractItemView::SelectionMode mode)
设置用户的选中模式:

  • SingleSelection: 最开始有1个当前项,没有选中项。只要点击,那么当前项和选中项永远相同,而且只有1个
    、、、、、、点击一个item,其他已经选中的item就会未选中。总之,全局只有1个item是选中的!!
    、、、、、、不可以使用ctrl多选,不可以使用shift多选。因为说了,只有1个item是选中的,就是鼠标点击的
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值