设为首页 加入收藏

TOP

13.2.3 派生新模型类(3)
2013-10-07 15:20:02 来源: 作者: 【 】 浏览:66
Tags:13.2.3 派生 模型

13.2.3  派生新模型类(3)

该函数将新创建的QModelIndex对象内部的行号,列号,指针(或者内部ID)设置为参数中的row、column、ptr(或者id)。本例调用的是第2个createIndex()函数,内部ID表示一个数据项在成员数组中的下标。该下标显然能够确定一个数据项的存储位置,所创建的QModelIndex对象当然也就是一个数据项的完整索引。

对于本例,如果父节点为模型类的不可见根节点,子数据项一定是二叉树的根节点。它在成员数组中的下标为0,而其行号、列号由index()函数的参数row,column指定(应该都为0),所以我们在行①创建该子数据项的索引。

如果父节点不是模型类的不可见根节点,它就一定是二叉树的一个非叶节点。行②取得它在成员数组中的位置,做一些简单的计算,即可求出子数据项在成员数组中的位置,最后调用createIndex()创建该数据项的索引。

代码段13 3,类TreeModel的实现(续),取自z:\examples\mvc\binary_tree\treemodel.cpp

  1. QModelIndex TreeModel::index ( int row, int column, const QModelIndex &     parent ) const   
  2. {  
  3.     if ( ! parent.isValid() )  
  4.         return createIndex(row, column, 0);     ①  
  5.     int parentparent_idx = parent.internalId();       ②  
  6.     int idx = parent_idx * 2 + ( row + 1 );  
  7.     return createIndex(row, column, idx );  
  8. }  
  9. QModelIndex TreeModel::parent ( const QModelIndex & index ) const  
  10. {  
  11.     if (index.internalId() == 0)                ③  
  12.         return QModelIndex();                   ④  
  13.     int parent_idx = (index.internalId() - 1 )/2;  
  14.     return createIndex( (parent_idx+1) % 2, 0, parent_idx );    ⑤  
  15. }  
  16. QVariant TreeModel::data ( const QModelIndex & index, int role ) const   
  17. {  
  18.     switch (role) {  
  19.     case Qt::DisplayRole:  
  20.         int value = numbers[ index.internalId() ];  
  21.         return QVariant( value );  
  22.     }  
  23.     return QVariant();  
  24. }  

成员函数parent()返回一个子数据项父节点的索引。参数index是这个子数据项的索引。如果这个索引的内部ID为0(行③),则这个子数据项是二叉树的根,其父节点是模型类的不可见根,行④调用QModelIndex的无参构造函数,创建并返回一个无效索引。如果子数据项不是二叉树的根,行④后的代码做一些简单的计算,求取父节点在成员数组中的位置,创建并返回其索引。这个子数据项的父节点可能是该子数据项的"爷"节点的左子节点或者右子节点,对应的行号可能会是0或者1。行⑤依据该子数据项的父节点在成员数组中的下标确定这个行号。

函数data()获取一个数据项中的数据。函数参数index是该数据项的索引,role是所要获取的数据子项的角色。本例只处理角色Qt::DisplayRole,该函数取得该数据项在成员数组中的下标,返回该数据项的数据,也就是二叉树节点中的整数,供视图类显示。对于其他角色,该函数调用QVariant的无参构造函数,构造一个表示"无效值"的QVariant对象,并返回给视图类,表明该模型类无法提供与角色role对应的数据子项,视图类自己应该为角色role指定一个默认值。比如,如果角色为Qt::BackgroundRole,视图类将会采用默认的白色作为显示数据项时的背景色。

重载了上述5个纯虚函数的类TreeModel就能够和Model/View框架中其他类协同工作了。由于这个模型类所表示的数据集是一棵树,我们采用类QTreeView来显示它的数据集,如代码段13 4所示。主函数只是简单地调用视图类的成员函数setModel(),建立起模型类和视图类两者之间的关联关系,两者就可以通过上述5个纯虚函数组成的最小接口进行信息交互。

代码段13 4,满二叉树例子的主函数,取自z:\examples\mvc\binary_tree\main.cpp

  1. int main(int argc, char *argv[])  
  2. {  
  3.     QApplication app(argc, argv);  
  4.     TreeModel  treeModel;  
  5.     QTreeView treeView(0);  
  6.     treeView.setModel( & treeModel );  
  7.     treeView.show();  
  8.     return app.exec();  
  9. }  

本例的模型类TreeModel只是提供了最基本的功能:当一个视图类需要显示数据集中的数据时,该类向视图类报告数据集的构造,并向视图类返回指定数据项中的数据,以使视图类能够"显示"模型类中的数据集。Model/View框架所具有的功能远比这丰富。在下面几节中,我们将向类TreeModel中添加新的功能,以展示Model/View框架的能力。

3.处理更多的角色

数据集的每个数据项包含多个『角色,数据子项』对,其中一些数据子项存放应用程序的数据,比如二叉树例子中每个数节点中的整数,而另外一些数据子项和这个数据项的显示相关,比如背景色、文字字体。当视图类需要显示某个数据项时,会查询这个数据项所包含的所有『角色,数据子项』对。上一节的模型类TreeModel仅向视图类报告Qt::DisplayRole角色对应的数据子项。本节扩展TreeModel的功能,使其能够向视图类报告更多角色对应的数据子项,以控制数据项的外观。我们的目标是使用红色、26磅字体显示叶节点。对于其他非叶节点,采用黑色、20磅显示。

如代码段13 5所示,我们只需修改模型类的data()函数即可达到这个目标。函数参数index指向被查询的数据项,role是所要查询的角色。由于我们需要更改某些节点的显示颜色,TreeModel必须处理角色Qt::ForegroundRole(行①)。index的成员函数internalId()返回QModelIndex对象的内部ID。本例中,这个内部ID表示当前数据项在模型类的成员数组的位置。行②依据位置判断被查询数据项是否为二叉树的叶节点。如果是,则返回一个红色刷子。否则,表示当前数据项不是叶节点,行④构造并返回一个无效QVariant对象,视图类将采用默认的黑色显示当前数据项。类似地,如果当前数据项是叶节点,行③后的代码返回26磅字体,否则,行④返回20磅字体,视图类将使用返回的字体显示当前数据项。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇13.2.3 派生新模型类(4) 下一篇13.2.3 派生新模型类(2)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: