创建新的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;

}

(转)Qt Model/View 学习笔记 (四)——创建新的Models的更多相关文章

  1. (转)Qt Model/View 学习笔记 (七)——Delegate类

    Qt Model/View 学习笔记 (七) Delegate  类 概念 与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件.一般来讲, view负责把数据展示 给用户,也 ...

  2. (转)Qt Model/View 学习笔记 (五)——View 类

    Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...

  3. (转)Qt Model/View 学习笔记 (二)——Qt Model/View模式举例

    Qt Model/View模式举例 Qt提供了两个标准的models:QStandardItemModel和QDirModel.QStandardItemModel是一个多用途的model,可用于表示 ...

  4. (转)Qt Model/View 学习笔记 (一)——Qt Model/View模式简介

    Qt Model/View模式简介 Qt 4推出了一组新的item view类,它们使用model/view结构来管理数据与表示层的关系.这种结构带来的 功能上的分离给了开发人员更大的弹性来定制数据项 ...

  5. (转)Qt Model/View 学习笔记 (三)——Model类

    Model类 基本概念 在model/view构架中,model为view和delegates使用数据提供了标准接口.在Qt中,标准接口QAbstractItemModel类中被定义.不管数据在底层以 ...

  6. (转)Qt Model/View 学习笔记 (六)——在views中选择数据项

    在views中选择数据项 概念 用于新的view类中的选择模型比Qt3中的模型有了很大的改进.它为基于model/view架构的选择提供了更为全面的描述.尽管对提供了的views来说,负责操纵选择的标 ...

  7. Qt Model/View学习(二)

    Model和View的搭配使用 DEMO pro文件 #------------------------------------------------- # # Project created by ...

  8. qt model/view/delegate

    Qt Model/View理解(一)---构造model https://blog.csdn.net/weixin_42303052/article/details/89233887 Qt Model ...

  9. Qt Model/View(官方翻译,图文并茂)

    http://doc.trolltech.com/main-snapshot/model-view-programming.html 介绍 Qt 4推出了一组新的item view类,它们使用mode ...

随机推荐

  1. 安卓Design包之Toolbar控件的使用

    转自:ToolBar的使用 ToolBar的出现是为了替换之前的ActionBar的各种不灵活使用方式,相反,ToolBar的使用变得非常灵活,因为它可以让我们自由往里面添加子控件.低版本要使用的话, ...

  2. MapReduce的手机流量统计的案例

    程序:(另外一个关于单词计数的总结:http://www.cnblogs.com/DreamDrive/p/5492572.html) import java.io.IOException; impo ...

  3. CF 13E. Holes 分块数组

    题目:点这 跟这题BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊  一模一样 分析: 分块数组入门题. 具体的可以学习这篇博文以及做国家集训队2008 - 苏煜<对块状链表的一 ...

  4. VSX规划Package文件

    VSX是VS扩展,可以针对不同项目编写插件,虽然接触VSX的时间并不多,但是当了解VSX后深刻感受到VSX的魅力. VSX的材料比较少,配置文件也很繁琐,当初我也走了不少弯路. 这篇文章将帮助您更好的 ...

  5. Ehcache(2.9.x) - API Developer Guide, Cache Manager Event Listeners

    About CacheManager Event Listeners CacheManager event listeners allow implementers to register callb ...

  6. Linux C编程--格式化I/O

    printf(格式控制,输入表列) 例:printf("%d%d",a,b) (1)d格式符:输出一个有符号的十进制整数 (2)c格式符:输出一个字符 (3)s格式符:输出一个字符 ...

  7. 基于 HTML5 的数据存储

    以前想做个静态网页APP.最初的思路是用本地文件存储数据,后来发现在手机上运行时,文件无法找到. 经过了长达几个月的搜索(实际也就几天),没有找到合适的方法. 就在绝望的时候,无意间搜到基于HTML5 ...

  8. JavaScript高级程序开发3笔记

      Js对象 注意:js基本数据类型不是对象,但是"abc".match()这种,可以调用对象的方法,是因为调用方法是临时产生了一个wrapper的包装对象,this指向它: Js ...

  9. html笔记——网页中视频播放,文字滚动

    转载地址:http://blog.chinaunix.net/uid-191945-id-2792153.html <代码1无限次播放> <EMBED src="地址&qu ...

  10. 使用AngularJS构建大型Web应用

    AngularJS是由Google创建的一种JS框架,使用它可以扩展应用程序中的HTML词汇,从而在web应用程序中使用HTML声明动态内容.在该团队工作的软件工程师Brian Ford近日撰写了一篇 ...