创建新的Models

介绍
model/view组件之间功能的分离,允许创建model利用现成的views。这也可以使用标准的功能 图形用户接口组件像QListView,QTableView和QTreeView来显示来自各种数据源的数据为。
QAbstractListModel类提供了非常灵活的接口,允许数据源以层次结构的形式来管理信息,也允许以某种
方式对数据进行插入、删除、修改和存储。它也提供了对拖拽操作的支持。
QAbstractListModel与 QAbstractTableModel为简单的非层次结构的数据提供了接口,对于比较简单的list和table models来说,这是不错的一个开始点。

设计一个Model
当我们为存在的数据结构新建一个model时,首先要考虑的问题是应该选用哪种model来为这些数据提供接口。
假如数据结构可以用数据项的列表或表来表示,那么可以考虑子类化 QAbstractListModel或 QAbstractTableModel
,既然这些类已经合理地对许多功能提供缺省实现。
然而,假如底层的数据结构只能表示成具有层次结构的树型结构,那么必须得子类化 QAbstractItemModel。
无论底层的数据结构采取何种形式,在特定的model中实现标准的 QAbstractItemModel API总是一个不错的主意,这使得可以使用更自然的方式对底层的数据结构进行访问。这也使得用数据构建model 更为容易,其他
的model/view组件也可以使用标准的API与之进行交互。

一个只读model示例
这个示例实现了一个简单的,非层次结构的,只读的数据model,它基于 QStringistModel类。它有一个 QStringList作为它内部的数据源,只实现了一些必要的接口。为了简单化,它子类化了 QAbstractListModel,这个基类提供了合理的缺省行为,对外提供了比 QAbstractItemModel更为简单的接口。当我们实现一个model时,不要忘了 QAbstractItemModel本身不存储任何数据,它仅仅提供了给views访问
数据的接口。
class StringListModel : public QAbstractListModel
 {
     Q_OBJECT

public:
     StringListModel(const QStringList &strings, QObject *parent = 0)
         : QAbstractListModel(parent), stringList(strings) {}

int rowCount(const QModelIndex &parent = QModelIndex()) const;
     QVariant data(const QModelIndex &index, int role) const;
     QVariant headerData(int section, Qt::Orientation orientation,
                         int role = Qt::DisplayRole) const;

private:
     QStringList stringList;
 };
除了构造函数,我们仅需要实现两个函数:rowCount()返回model中的行数,data()返回与特定model index对应的数据项。具有良好行为的model也会实现headerData(),它返回tree和table views需要的,在标题中显示的数据。
因为这是一个非层次结构的model,我们不必考虑父子关系。假如model具有层次结构,我们也应该实现index()与parent()函数。

Model的尺寸
我们认为model中的行数与string list中的string数目一致:
int StringListModel::rowCount(const QModelIndex &parent) const
 {
     return stringList.count();
 }
在缺省情况下,从QAbstractListModel派生的model只具有一列,因此不需要实现columnCount()。

Model 标题与数据
 QVariant StringListModel::data(const QModelIndex &index, int role) const
 {
     if (!index.isValid())
         return QVariant();

if (index.row() >= stringList.size())
         return QVariant();

if (role == Qt::DisplayRole)
         return stringList.at(index.row());
     else
         return QVariant();
 }
QVariant StringListModel::headerData(int section, Qt::Orientation orientation,
                                      int role) const
 {
     if (role != Qt::DisplayRole)
         return QVariant();

if (orientation == Qt::Horizontal)
         return QString("Column %1").arg(section);
     else
         return QString("Row %1").arg(section);
 }
一个数据项可能有多个角色,根据角色的不同输出不同的数据。上例中,model中的数据项只有一个角色 ,
DisplayRole,然而我们也可以重用提供给DisplayRole的数据,作为别的角色使用,如我们可以作为ToolTipRole来用。

可编辑的model
上面我们演示了一个只读的model,它只用于向用户显示,对于许多程序来说,可编辑的list model可能更有用。我们只需要给只读的model提供另外两个函数flags()与setData()的实现。下列函数声明被添加到类定义中:
     Qt::ItemFlags flags(const QModelIndex &index) const;
     bool setData(const QModelIndex &index, const QVariant &value,
                  int role = Qt::EditRole);

让model可编辑
delegate会在创建编辑器之前检查数据项是否是可编辑的。model必须得让delegate知道它的数据项是可
编辑的。这可以通过为每一个数据项返回一个正确的标记得到,在本例中,我们假设所有的数据项都是
可编辑可选择的:
Qt::ItemFlags StringListModel::flags(const QModelIndex &index) const
 {
     if (!index.isValid())
         return Qt::ItemIsEnabled;

return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
 }
我们不必知道delegate执行怎样实际的编辑处理过程,我们只需提供给delegate一个方法,delegate会使用它对model中的数据进行设置。这个特殊的函数就是setData():
bool StringListModel::setData(const QModelIndex &index,
                               const QVariant &value, int role)
 {
     if (index.isValid() && role == Qt::EditRole) {

stringList.replace(index.row(), value.toString());
         emit dataChanged(index, index);
         return true;
     }
     return false;
 }
当数据被设置后,model必须得让views知道一些数据发生了变化,这可通过发射一个dataChanged() 信号实现。
因为只有一个数据项发生了变化,因此在信号中说明的变化范围只限于一个model index。
插入,删除行
在model中改变行数与列数是可能的。当然在本列中,只考虑行的情况,我们只需要重新实现插入、删除
的函数就可以了,下面应在类定义中声明:
     bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex());
     bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());
既然model中的每行对应于列表中的一个string,因此,insertRows()函数在string list  中指定位置插入一个空string,
父index通常用于决定model中行列的位置,本例中只有一个单独的顶级项,困此只需要在list中插入空string。
bool StringListModel::insertRows(int position, int rows, const QModelIndex &parent)
 {
     beginInsertRows(QModelIndex(), position, position+rows-1);

for (int row = 0; row < rows; ++row) {
         stringList.insert(position, "");
     }

endInsertRows();
     return true;
 }
beginInsertRows()通知其他组件行数将会改变。endInsertRows()对操作进行确认与通知。
返回true表示成功。
删除操作与插入操作类似:
bool StringListModel::removeRows(int position, int rows, const QModelIndex &parent)
 {
     beginRemoveRows(QModelIndex(), position, position+rows-1);

for (int row = 0; row < rows; ++row) {
         stringList.removeAt(position);
     }

endRemoveRows();
     return true;
 }

转载自:http://www.cppblog.com/yuanyajie/archive/2007/06/18/26555.html

Qt Model/View 学习笔记 (四)相关推荐

  1. Qt Model/View 学习(4) - 实现自己的QAbstractTableModel类(支持显示与修改)

    目录 0. 前言 1. Data设计 2. Model类设计 2.1 数据显示与对齐.字体修改 2.2 数据修改 3. 小结 0. 前言 可算到了这一篇了! 上一篇文章中把Qt::ItemDataRo ...

  2. IOS学习笔记(四)之UITextField和UITextView控件学习

    IOS学习笔记(四)之UITextField和UITextView控件学习(博客地址:http://blog.csdn.net/developer_jiangqq) Author:hmjiangqq ...

  3. Ethernet/IP 学习笔记四

    Ethernet/IP 学习笔记四 EtherNet/IP Quick Start for Vendors Handbook (PUB213R0): https://www.odva.org/Port ...

  4. (一) Qt Model/View 的简单说明

    目录: (一) Qt Model/View 的简单说明 .预定义模型 (二)使用预定义模型 QstringListModel例子 (三)使用预定义模型QDirModel的例子 (四)Qt实现自定义模型 ...

  5. JavaScript学习笔记(四)(DOM)

    JavaScript学习笔记(四) DOM 一.DOM概述 二.元素对象 2.1 获取方式 (1).通过ID获取一个元素对象,如果没有返回null (2).通过`标签名`获取一组元素对象,,如果没有返 ...

  6. Qt Model/View(MVD)模型分析

           最近在看Qt的Model/View Framework,在网上搜了搜,好像中文的除了几篇翻译没有什么有价值的文章.E文的除了Qt的官方介绍,其它文章也很少.看到一个老外在blog中写道M ...

  7. QT Model/View 编程:MVC模型视图编程:实例实现(二)

    目录 样例001:现有模型中使用视图Using views with an existing model 样例002:使用模型索引 样例003:使用模型 样例004:使用模型的多个视图 样例005:委 ...

  8. C#可扩展编程之MEF学习笔记(四):见证奇迹的时刻

    前面三篇讲了MEF的基础和基本到导入导出方法,下面就是见证MEF真正魅力所在的时刻.如果没有看过前面的文章,请到我的博客首页查看. 前面我们都是在一个项目中写了一个类来测试的,但实际开发中,我们往往要 ...

  9. RabbitMQ学习笔记四:RabbitMQ命令(附疑难问题解决)

    RabbitMQ学习笔记四:RabbitMQ命令(附疑难问题解决) 参考文章: (1)RabbitMQ学习笔记四:RabbitMQ命令(附疑难问题解决) (2)https://www.cnblogs. ...

最新文章

  1. Java项目:前台+后台精品水果商城系统设计和实现(java+Springboot+ssm+mysql+jsp+maven)
  2. linux 进入单用户模式修改root密码
  3. 于XAML导入命名空间的代码
  4. C++/STL Bitset (转)
  5. python 学习之输出流重定向
  6. Windows Phone xml数据的解析与绑定
  7. Microsoft REST API指南
  8. Python风格总结:Python基础-类变量和实例变量
  9. MySQL与Oracle的语法区别详细对比 (转)
  10. 商淘软件已成为ThinkPHP商城系统之标杆产品
  11. ubantu14.04搜狗拼音安装
  12. asp上传头像mysql_asp 会员头像上传 代码
  13. matlab创作歌曲——《月半小夜曲》
  14. 大数据开发工程师必看书籍
  15. B-Spline曲线的导数
  16. 一个笼子里有鸡和兔,现在只知道里面一共有 40 个头,100 只脚,鸡兔各有多少只?
  17. 芝麻粒助力,好友辅助攻略,快速获取芝麻粒攒芝麻粒攻略一个月至少30粒
  18. 期刊论文需要查重吗?
  19. 2018 mac下安装redis 和 redis可视化工具rdm并且连接redis
  20. linux,rpm, tar, gz, bz, bz2, rar, zip, lha, deb, 解压

热门文章

  1. [bzoj1025][SCOI2009]游戏 (分组背包)
  2. 细说angular Form addControl方法
  3. hrbust 1616 密码锁(广搜)
  4. BootStrap入门教程 (四)
  5. python语法教程-Python语法教程总结规范
  6. python怎么把数据写入txt-如何将python中文件写入TXT
  7. python打开界面是什么样的-python学习笔记(图形用户界面)
  8. 看漫画学python电子书-看漫画学Python(有趣有料好玩好用全彩版)
  9. python现在好找工作吗-转行学Python好找工作吗?
  10. php和python区别-php与python的区别