qt4MV编程:4 创建新的模式

创建新的模式
 
介绍
设计模式
只读模式例子
       模是的规模
       模式头和数据
可编辑模式
       是模式可编辑
       插入和删除行
后续步骤
 
介绍
将model/view组件功能上分离运行创建模式可以利用已有的视图。这种方法允许我们使用标准的图形用户接口显示各种源的数据,标准图形接口如:QListView,QTableView和QTreeView.
类QAbstractItemModel提供了非常灵活的接口,支持使用继承结构安排信息的数据源,这种接口允许插入数据、删除数据、修改数据或者对数据采用一些方式的排序。而且还支持拖放操作。
类QAbstractListModel和QAbstractTableModel提供了简单非继承结构数据的接口,作为简单列表和表格模式的起点更容易使用。
本节,为了解释model/view体系结构的基本原则,我们创建一个只读的模式。本节的后部分,我们也会调整这个简单的模式,让条目可以让用户修改。
要看更复杂的模式例子,请看例“简单树形模式”。
对类QAbstractItemModel的子类的需求,在“模式子类化参考”文档中有详细的描述。
 
设计一个模式
       在为现存的数据结构创建一个模式时,创建何种类型的模式来为数据提供接口是非常重要的。如果数据结构可以当作列表或表格来看待,那么可以继承类QAbstractListModel或QAbstarctTableModel,这些类提供了许多函数的合适的缺省实现。
然而,如果底层的数据结构只能使用树形结构来显示,那么必须继承类QAbstractItemModel.在例“简单的树形模式”中将采用这样的方法。
在本节中,我们将实现一个基于一个字符串列表的简单模式,所以基于类QAbstractListModel是非常理想的。
不管底层数据机构采用什么形式,在特定的模式中补充QAbstractItemModel的API是非常好的想法,通过这些接口,可以更自然的访问底层的数据结构。这样使得模式和数据移植更容易,同时还是允许其他的一般model/view组件通过使用标准API和数据交互。下面的例子提供了一个用户定义的构造函数,就是为了这个目的。
 
一个只读的模式例子
这个例子比较简单,没有继承结构,只读数据,而且基于标准的QStringListModel。它只有一个QStringList作为它的内部数据源,且只实现了创建一个有用的模式所必须实现的。为了使实现更简单一点,我们继承自QAbstractListModel,因为它为列表模式定义了缺省的行为,并且它比类QAbstractItemModel提供的接口更简单。
实现一个模式时很重要的是要记住QAbstractItemModel本身不存储数据,它只是提供接口供视图来存取数据。对于一个小的只读模式,只需实现很少的函数,因为默认的实现已经完成了大部分的接口。类声明如下:

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::Qrientation orientation,

                                          int role = Qt::DisplayRole ) const;

private:
       QStringList stringList;
};
 
除了模式的构造函数外,我们只需要实现两个函数:rowCount()函数返回模式中的行数,data()返回指定索引的数据条目。
       行为友好的模式也实现headerData(),为树形和表格视图一些信息来显示在它们的头部。
      注意到这是一个非继承结构的模式,所以我们用不着担心父子关系。如果我们的模式是继承关系,我们也需要实现index()和parent()函数。
       字符串列表存放在内部私有成员变量中。
 
模式的测度
我们想要模式中的行数和字符串列表中的字符数相同。我们在函数rowCount()中这样实现:

int   StringListModel::rowCount( const QModelIndex & parent ) const

{

       return stringList.count();

}
 
这个模式非继承结构,我们很放心的忽略父条目的模式索引。默认的,继承自QAbstractListModel的模式只包含一列,我们不必要重新实现函数columnCount()。
 
模式头和数据
对于视图中的条目,我们想要返回字符串列表的字符串。函数data()用来返回又索引参数指定的数据条目:

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对象。
       有些视图,如QTreeView和QTableView,能够和数据条目一起显示头。如果我们的模式是在有头的视图中显示,我们想要头显示行数和列数。我们可以通过继承headerData()函数来显示头信息:

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 );

}
同样,如果模式索引有效并且角色是我们支持的我们才返回一个有效的QVariant。当考虑到返回精确数据的时候我们也要考虑头的倾向。
       不是所有的视图和条目数据一起显示头的,并且即使是那些显示头的通过配置也可以隐藏头的。虽然如此,还是建议你实现函数headerData(),模式应该提供关于数据的相关信息。
       每个条目可以有多个角色,不同的角色有不同的数据。我们例子中的条目只有一个角色,DisplayRole,我们就不会根据不同角色返回数据。然而,我们可以在其他角色中复用DisplayRole的数据,比如角色ToolTipRole中,视图在工具提示中可以显示信息。
 
一个可编辑的模式
       上面的只读模式展示了对用户是如此简单的选择,但是,对于很多程序,一个可编辑的模式会更有用。我们可以修改只读模式使它的条目可以编辑,需要实现两个额外的函数:flags()和setData()。在类定义中增加下面两个函数的声明:

Qt::ItemFlags flags( const QModelIndex & index ) const;

bool setData( const QModelIndex& index, const QVariant & value,

                     int role = Qt::EditRole );

 
使模式可编辑
       代理在创建编辑器之前会检查条目是否可以编辑。模式必须让代理知道它的条目使可编辑的。在模式中,我们通过返回每个条目的一个正确标识来实现这个功能;这样,我们使所有条目既可以选择也可以编辑:

Qt::ItemFlags StringListModel::flags( const QModelIndex& index ) const

{

       if( !index.isValid() )

              return Qt::ItemIsEnabled;

 

       return QAbstractItemModel::flags( index) | Qt::ItemIsEditable;

}
 
注意,我们并不需要知道代理是如何处理实际编辑的。我们只需要为代理提供设置模式中数据的方法。由函数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;

}
 
在例子中,由模式索引指定的字符串列表条目被提供的值替换。然而,在我们修改字符串列表之前,我们必须保证模式索引有效,条目是正确类型,还有角色也支持。通常,我们强调角色是EditRole是因为标准代理就是使用这个角色。这个模式中的底层数据对所有角色都相同,所以这个细节使和标准部件集成更容易。
       当数据设置后,模式必须让视图知道数据发送变化。我们发送信号dataChanged()。只有一个数据发生变化,条目范围只有一个模式索引。
 
插入和删除行
       在模式中很可能需要改变行数和列数。在字符串列表模式中,只需改变行数才有意义,所以我们只需重载插入和删除行函数。在类定义中声明:

bool insertRows( int position, int rows, const QModelIndex& index = QModelIndex() );

bool removeRows( int position, int rows, const QModelIndex& index = QModelIndex() );

 
由于本例中,行对应列表中的一个字符串,函数insertRows()在定位之前插入一些空串。字符串的数量等于指定插入的行数。
       父对象索引一般用于确定插入行的位置。在例子中,我们只有一个简单的顶层字符串列表,所以我们只是将空串插入到这个列表中。

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;]

}
 
在删除底层数据前总是要调用函数beginRemoveRows(),并且指定第一个和最后一个要删除的行。这样允许在数据可用前其他组件可以访问数据。行移除后,模式发送endRemoveRows()来完成操作并通知其他组件模式测度发送改变。
 
下面步骤
       我们可以显示这个模式,或者其他的任何模式,使用类QListView在一个垂直的列表中显示模式的条目。对于字符串列表模式,这个视图提供了默认的编辑器,可以用来控制条目。在章节“视图类”中我们将解释标准视图的能用的可能性。
       在文档“Model Subclassing Reference”中详细讨论了QAbstractItemModel继承的要求,并提供了一个关于使用各种模式特性纯虚函数的指导。
 
http://doc.trolltech.com/4.3/model-view-creating-models.html#an-editable-model
 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值