您的位置:首页 > 其它

QSortFilterProxyModel的使用

2013-01-30 08:54 791 查看
QSortFilterProxyModel类提供在其他的model和view之间排序和过滤数据的支持

QSortFilterProxyModel可以用来对item进行排序,筛选,它把一个model的source结构通过model的index结构map到他新提供的index里面,这种方法允许一个model重新组织,当和他相关联的view,不需要在数据上请求任何转换,也不需要复制内存中的数据

代码如下

QTreeView *treeView = new QTreeView;

MyItemModel *sourceModel = new MyItemModel(this);

QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this);

proxyModel->setSourceModel(sourceModel);

treeView->setModel(proxyModel);

此时,排序和过滤都不可用,原始的数据在view中显示,通过QSortFilterProxyModel做的任何改动都会被作用在原始的model中

QSortFilterProxyModel对于原始的model来讲就相当于一个包装工具,如果想把原始的QModelIndex转换成可排序/过滤的model,或者反之亦然,使用 mapToSource(), mapFromSource(), mapSelectionToSource(), and mapSelectionFromSource()这些方法

默认的,当原始的model改变时候,它不会动态自动重新排序和重新过滤数据,但可以通过设置dynamicSortFilter性质来改变,方法:void setDynamicSortFilter (bool enable)

具体看例子 Basic Sort/Filter Model 和 Custom Sort/Filter Model

QTableView和QTreeView有一个sortingEnabled性质,控制着view是否可以通过点击表头来排序,例如treeView->setSortingEnabled(true); 默认是不可排序的

当这个性质打开时候,点击header就会对本列的item排序,通过重复点击header,用户可以交替的看到升序和排序的排序



MVC中,在场景scene后,view可以调用model的虚函数sort()来记录model的数据,为了可以使自己的数据可以排序,我们可以使用sort()方法,或者使用QSortFilterProxyModel来做这个model的外包装,QSortFilterProxyModel提供了共有的sort()方法来操作items的sortRole(默认是Qt::DisplayRole),包括int,QString,QDateTime

传统的排序行为可以通过子类化QSortFilterProxyModel和使用lessThan()方法,lessThan()方法用来对比items,例如:

bool MySortFilterProxyModel::lessThan(const QModelIndex &left,

const QModelIndex &right) const

{

QVariant leftData = sourceModel()->data(left);

QVariant rightData = sourceModel()->data(right);

if (leftData.type() == QVariant::DateTime) {

return leftData.toDateTime() < rightData.toDateTime();

} else {

QRegExp *emailPattern = new QRegExp("([//w//.]*@[//w//.]*)");

QString leftString = leftData.toString();

if(left.column() == 1 && emailPattern->indexIn(leftString) != -1)

leftString = emailPattern->cap(1);

QString rightString = rightData.toString();

if(right.column() == 1 && emailPattern->indexIn(rightString) != -1)

rightString = emailPattern->cap(1);

return QString::localeAwareCompare(leftString, rightString) < 0;

}

}

Filetering

除了排序外,QSortFilterProxyModel可以用来隐藏那些和过滤器不匹配的items,过滤器使用 QRegExp类对象,对一个给定的列, QRegExp对象可以用来匹配一个正则表达式,一个通配符,一个字符串,例如

proxyModel->setFilterRegExp(QRegExp(".png", Qt::CaseInsensitive,QRegExp::FixedString));

proxyModel->setFilterKeyColumn(1);

对于分层的models,过滤器对他所有的孩子都有用,如果父item不匹配过滤器,孩子item也不会显示,

通常的一个用法是让用户通过QLineEdit指定过滤器正则表达式,通配符,然后通过发送信号textChanged()信号,使用 setFilterRegExp(), setFilterWildcard(), or setFilterFixedString()来响应过滤器

一般的过滤行为可以在实现filterAcceptsRow() and filterAcceptsColumn()函数,下面的例子中,函数实现中忽略了 filterKeyColumn性质,只在第一和第二三列实现过滤

bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow,const QModelIndex &sourceParent) const

{

QModelIndex index0 = sourceModel()->index(sourceRow, 0, sourceParent);

QModelIndex index1 = sourceModel()->index(sourceRow, 1, sourceParent);

QModelIndex index2 = sourceModel()->index(sourceRow, 2, sourceParent);

return (sourceModel()->data(index0).toString().contains(filterRegExp())

|| sourceModel()->data(index1).toString().contains(filterRegExp()))

&& dateInRange(sourceModel()->data(index2).toDate());

}

如果工作中有大量的过滤器要使用,频繁的调用invalidateFilter(),使用reset()可能更有效,具体视你的model的实现,然而,reset()返回代理model给他原始的model,丢失选择信息,将会引起代理model重新注入
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: