设为首页 加入收藏

TOP

【Qt6】列表模型——抽象基类(一)
2023-09-23 15:44:27 】 浏览:588
Tags:Qt6

列表模型(Item Model),老周没有翻译为“项目模型”,因为 Project 和 Item 都可以翻译为“项目”,容易出现歧义。干脆叫列表模型。这个模型也确实是为数据列表准备的,它以 MVC 的概念为基础,在原始数据和用户界面视图之间搭建桥梁,使两者可以传递数据(提取、修改)。

Qt 里面使用列表控制比较复杂,需要先创建模型(Model)。当然,也有像 QListWidget 类这样已经封装好,开箱即食的,这个后面再扯,现在咱们的重点是弄清楚 Item Model 是啥玩意儿。

这里所说的 Item Model 并不是真正的数据,应该说算是个控制器。当用户界面要显示数据时,模型负责从原始数据那里提取值,再把值传到界面上呈现;如果用户界面要修改数据,通过输入框(QLineEdit等)输入/修改内容,然后传给模型,模型负责修改原始数据。这么看来,视图和原始数据不是直接通信的,模型就成了“中间商”。这个“中间商”可以不赚差价(按原始数据的样子呈现),也可能赚差价(把原始数据加工一下再让你看)。

列表模型有一个抽象基类,叫 QAbstractItemModel;对应地,视图组件也有一个抽象基类,叫 QAbstractItemView。另外,在模型和视图之间还有一个“代理人”,抽象基类叫 QAbstractItemDelegate,它干吗的呢?这是专业经纪人,负责门面工作。比如,在视图组件里呈现数据时用什么字体,什么颜色来绘制文本,用什么方式从模型提取数据等;在编辑数据时,有什么控件来输入文本。以及在编辑结束后,输入的内容怎么传给模型等。日常使用时咱们用到 QAbstractItemDelegate 不多,除非你自己想为数据项绘制 UI,或用自定义的编辑组件。如果只是改改外观什么的,还不如用 QSS 方便。

行了,不扯太远了,咱们只要知道这几个基类之间的关系就行了。咱们的重点还是放在 QAbstractItemModel 类上面。

QAbstractItemModel 有几个纯虚函数是必须在派生类中重写的:

1、index 方法,声明如下:

virtual QModelIndex index(
             int row, 
             int column,
             const QModelIndex &parent = QModelIndex()) const = 0;

列表模型中的索引,专门用一个叫 QModelIndex 的类表示。index 方法是根据传入的参数,返回 QModelIndex 对象。之所以要用 QModelIndex 类来表示列表项的索引,是因为它是由几个值组成的:

a、行号;
b、列号;
c、父索引。

Qt 中的列表模型用的是二维表结构,即由行和列组成,就像这样:

问:D在哪里?

答:row = 1,column = 0。

每个项又可以包含父级节点和子级节点,但上面的二维表只有一层,没有父级,所以它的 parent = QModelIndex()。用默认构造函数创建的 QModelIndex 表示无效索引,即行号是 -1,列号是 -1,无父无子。

综上所言,D 的索引就是:row = 1,col = 0,parent = QModelIndex()。

这个模型真正可怕的地方在于,每个索引都有父、子级。于是你可以构想下面这么恐怖的列表:

Root是一个无效的索引,可以认为是顶层的”父级“。A、B、C、D、E、F 的父级都是 Root,行列号由0开始编排,A在第一行第一列,所以 row=0,col=0,parent=Root。E有子节点,即 M、N、O、P,然后MNOP的行号和列号也要从 0 重新计算,即 N 的索引是 row=0, col=1, parent=E。最后,Q 这厮又有子节点,是一个只有一行的列表:R、S、T。于是,RST的行列号也重新计算。即 R 的索引是 row=0, col=0, parent=Q。

不过,实际使用时,一般不需要构建这么神的数据结构,而且这玩意放到用户界面上还不知道怎么显示好呢。毕竟,咱们在界面上常见的视图也就以下三种:

1)、多行,只有一列,这就相当于像数组这样的数据了。用 QListView 组件来呈现;

2)、一级二维表,由行、列组成,由 QTableView 组件呈现;

3)、多级节点,典型的就是 QTreeView 组件了。Qt 的 TreeView 比 .NET 的控件多了一个特点——可以在显示多级节点的同时显示表格。但要注意的是,只有首列才支持父子节点。所以,对于 QTreeView 视图,构建这样的数据也足够了:

2、parent 方法。它的声明如下:

virtual QModelIndex parent(const QModelIndex &child) const = 0;

返回 child 节点的父级节点,对于只有一层的列表,返回 QModelIndex() 即可。

3、rowCount 方法。声明如下:

virtual int rowCount(const QModelIndex &parent = QModelIndex()) const = 0;

返回原始数据有总共有多少行。

4、columnCount 方法。它的声明如下:

virtual int columnCount(const QModelIndex &parent = QModelIndex()) const = 0;

该方法返回原始数据有多少列,如果是数组之类的,返回 1。

5、data 方法。声明如下:

virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const = 0;

这是个重要的成员,它要根据 index 参数指定的索引,返回数据项的值。这里要说一下叫”数据角色“的概念。说通俗不易懂一点就是返回的值的用途。比如,role 参数的默认值指定了 DisplayRole,意思就是你返回的值是要显示在用户界面上的,就是你想让用户看到的文本。Qt::ItemDataRole 枚举定义了一系列数据角色。

enum ItemDataRole {
    DisplayRole = 0,               // 显示在界面的内容
    DecorationRole = 1,          // 和文本一起显示的图标,类型一般是QIcon
    EditRole = 2,                    // 当编辑数据时,返回给用户看的值
    ToolTipRole = 3,                // 显示在工具提示中的文本
    StatusTipRole = 4,            // 显示在状态栏中的文本
    WhatsThisRole = 5,           // 帮助信息,显示在”这是啥?“提示中
    // Metadata
    FontRole = 6,                    // 呈现数据时用啥字体
    TextAlignmentRole = 7,      // 文本的对齐方式
    BackgroundRole = 8,          // 返回画刷对象,用来绘制列表项的背景
    ForegroundRole = 9,           // 文本的颜色
    CheckStateRole = 10,         // 如果界面上显示了 checkbox,那么返回checkbox的状态(选中?未选中?未知?)
    // Accessibility
    AccessibleTextRole = 11,     // 简练的辅助信息。用于像”讲述人“这些辅助工具
    AccessibleDescriptionRole = 12,    //详细辅助信息,用于像”讲述人“类似的辅助工具
    // More general pur
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇2.10 PE结构:重建重定位表结构 下一篇2.12 PE结构:实现PE字节注入

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目