设为首页 加入收藏

TOP

13.2.3 派生新模型类(6)
2013-10-07 15:18:29 来源: 作者: 【 】 浏览:62
Tags:13.2.3 派生 模型

13.2.3  派生新模型类(6)

6.编辑数据项

Qt的Model/View框架不但可以将数据集中的数据呈现给用户,它还允许用户编辑每个数据项。并非所有数据项都是可以编辑的,模型类负责确定哪些是可编辑的,哪些是不可编辑的。当用户双击某个数据项试图对其进行编辑时,视图类会调用模型类的成员函数flags(),查询目标数据项是否可编辑。如果是,视图类会调用模型类的data()函数,获取目标数据项中角色Qt::EditRole对应的数据子项,送给一个编辑器控件进行编辑。用户完成编辑后,Qt的Model/View框架会调用模型类的setData()函数,把编辑器中的编辑结果传递给模型类,令模型类修改目标数据项中的数据。

模型类在修改完毕目标数据项的值之后,应该触发一个dataChanged()信号。Qt的Model/View框架会将这个信号发送给所有与这个模型类绑定的视图对象,以重新绘制目标数据项。最后这个步骤有两个作用。

(1)如前文所述,委托类负责绘制一个数据项。当用户编辑一个数据项时,编辑器控件会采用不同于委托类的方式显示一个数据项。例如,设目标数据项中存放着一个整数,视图类只会简单地显示这个整数,而编辑器控件使用一个编辑框显示、编辑这个整数,同时还在编辑框的右侧显示一个上箭头、一个下箭头,用户按这两个箭头也可以更改整数的值。当用户完成一个数据项的编辑时,编辑器控件会被关闭,委托类必须重新绘制该数据项。

(2)如果有多个视图对象与一个模型类对象绑定,某个数据项被更改后,必须通过所有的视图对象,以重新绘制这个数据项,否则,只有被编辑的那个视图显示的是正确的值,其他视图显示的都是较老的值。

当视图类查询一个目标数据项中角色Qt::EditRole对应的数据子项时,模型类将这个数据子项以类型QVariant返回。Qt的Model/View框架依据这个QVariant内部存放的数据的类型,选择适当的编辑器控件对其中的数据进行编辑,程序员不必定义新的编辑器控件。当然,如果程序员不喜欢默认的编辑器控件,当然也可以创建新的编辑器控件。本节演示如何使用默认的编辑器控件对前文所述的满二叉树进行编辑。

我们约定用户只可以编辑满二叉树的叶节点,不可以编辑任何非叶节点。当某个叶节点的值变化时,该叶节点到根节点路径上所有节点的值都应该被更改,以满足约束条件"父节点的值等于两个子节点值之和"。

如代码段13 8所示,模型类TreeModel重载QAbstractItemModel的虚函数flags(),向视图类返回一个标志变量,表明某个数据项是否可编辑。当一个数据项是叶节点时,返回的标志变量包含Qt::ItemIsEditable,表明该数据项是可编辑的。如果一个数据项是可编辑的,Qt的Model/View框架会调用TreeModel的data()函数,以角色Qt::EditRole查询对应的数据子项,行①后的代码返回该数据项中存放的整数。Model/View框架显示一个适当的编辑器,以允许用户对这个整数进行编辑。

代码段13 8,编辑满二叉树的叶节点,取自z:\examples\mvc\binary_tree_editable\treemodel.cpp

  1. Qt::ItemFlags TreeModel::flags(const QModelIndex & index) const  
  2. {  
  3.     if ( index.internalId() < N/2 )  
  4.         return Qt::ItemIsSelectable |  Qt::ItemIsEnabled ;  
  5.     else  
  6.         return Qt::ItemIsSelectable |   Qt::ItemIsEnabled  |                Qt::ItemIsEditable;  
  7. }  
  8. QVariant TreeModel::data ( const QModelIndex & index, int role  ) const   
  9. {  
  10.     int value;  
  11.     switch (role) {  
  12.     case Qt::DisplayRole:  
  13.         value = numbers[ index.internalId() ];  
  14.         return QVariant( value );  
  15.     case Qt::EditRole:          ①  
  16.         value = numbers[ index.internalId() ];  
  17.         return QVariant( value );  
  18.     }  
  19.     return QVariant();  
  20. }  
  21.  
  22. bool TreeModel::setData(const QModelIndex & index, const QVariant & value,  int role)  
  23. {  
  24.     if (role != Qt::EditRole) return true;    
  25.     int id = index.internalId();  
  26.     while (1) {                 ②  
  27.         if ( id >= N/2 )   
  28.             numbers[id] = value.toInt();  
  29.         else   
  30.             numbers[id]  = numbers[2 * id + 1] + numbers[ 2 * id + 2];  
  31.           
  32.         QModelIndex idx = createIndex(1,0,id);  
  33.         emit dataChanged(idx,idx);  ③  
  34.         if ( id == 0 ) break;  
  35.         id = ( id - 1 ) /2;  
  36.     };  
  37.     return true;  
  38. }  

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

评论

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