文档章节

利用C++11的function和bind功能,实现QStandardItemModel的通用遍历函数

尘中远
 尘中远
发布于 2016/05/12 23:51
字数 1153
阅读 17
收藏 0
点赞 2
评论 0
在使用Qt的树形视图和表格视图QTableView和QTreeView时,经常需要遍历所有条目,每种功能都写一个遍历函数既麻烦又不符合编程最简原则,因此,写一个通用的遍历函数是很必要的(类似于std::for_each),对于遍历时实现的功能不一样,可以通过函数指针来代替需要实现的功能。

在讲这个之前,需要了解 std::function和std::bind,具体可以自行谷歌。

由于这个遍历函数可能经常用到,因此可以写一个类的静态函数或者是全局函数。

下面把这个功能封装在一个类里

类的头文件如下:
#include <QStandardItemModel>
#include <functional>
class QStandardItemModelEx
 {
 public:
     QStandardItemModelEx(){}
     ~QStandardItemModelEx(){}
     ///
     /// \brief callback_ergodicFun_ptr 回调函数指针,bool f(QStandardItem*),bool用于决定是否继续,如果为true就继续递归,如果为false就停止递归
     ///
     typedef std::function<bool(QStandardItem*)> callback_ergodicFun_ptr;

     //typedef void(*callback_ergodicFun_ptr)(QStandardItem*);
     static void ergodicAllItem(QStandardItemModel* model,callback_ergodicFun_ptr pFun);
     static bool ergodicItem(QStandardItem* item,callback_ergodicFun_ptr pFun);
 private:
 };

这里使用C++11的新特性function(环境 VS2010),定义一个函数指针用于回调实现功能。
函数 ergodicAllItem用于遍历所有项目, ergodicItem用于遍历项目下的所有子项目。回调函数返回bool用于决定是否继续,如果为true就继续遍历,如果为false就停止遍历
为了简单起见,下面用递归实现遍历( ergodicItem是尾递归函数
 
void QStandardItemModelEx::ergodicAllItem(QStandardItemModel* model,callback_ergodicFun_ptr pFun)
{
    int rows = model->rowCount();
    int column = model->columnCount();
    for (int i=0;i<rows;++i)
    {
        for(int j=0;j<column;++j)
        {
            QStandardItem* item = model->item(i,j);
            if (item)
            {
                if(!ergodicItem(item,pFun))
                    return;
            }
        }
    }
}

bool QStandardItemModelEx::ergodicItem(QStandardItem* item,callback_ergodicFun_ptr pFun)
{
    int rows = item->rowCount();
    int column = item->columnCount();
    for (int i=0;i<rows;++i)
    {
        for(int j=0;j<column;++j)
        {
            QStandardItem* childItem = item->child(i,j);
            if (childItem)
            {
                if(!ergodicItem(childItem,pFun))
                    return false;
            }
        }
    }
    return pFun(item);
}




用这两个函数就可以遍历所有的项目了,而遍历时需要的动作,就通过回调函数实现。

回调函数即可写在类里,也可以写为全局函数,若除了 QStandardItem * 还需要别的参数,那么可以用std::bind帮忙。

下面举一个例子
例子功能是通过关键字高亮条目。在使用QTreeView或QTableView时,在条目多的情况下,需要搜索某些条目,对搜索结果进行高亮,这时,就需要遍历整个View里的条目,对符合的条目进行高亮
遍历的函数已经写好,现在缺少的是回调的函数,由于遍历的函数使用的函数指针是 std : : function ,因此回调函数即可写为全局函数也可以写为类成员函数
回调函数声明:
bool callback_hightLightItem(QStandardItem* item,const QStringList keys);
回调函数实现:
bool callback_hightLightItem(QStandardItem* item,const QStringList keys)
{   
    QString str = item->text();
    if (is_match_string(str,keys))
    {
        item->setData(QVariant(QColor(237,100,100,180)),Qt::BackgroundRole);
    }
    else
    {
        item->setData(QVariant(),Qt::BackgroundRole);
    }
    return true;
}

使用QStandardItem的setData函数,设置角色为Qt::BackgroundRole,即可设置背景颜色。
实现函数中is_match_string函数是用来检测是否符合关键字,如果符合关键字,就返回true,符合关键字就给条目背景赋予不同的颜色,否则就把颜色消除。
回调函数返回true,意味着一直遍历,直到所有遍历完成。

通过按钮pushButton_search来触发搜索功能。 pushButton_search函数的槽如下:
void MainWindow : :on_pushButton_search_clicked()
{
    QString str  = ui - >lineEdit_search - >text(); //获取关键字
     if (str.isEmpty())
         return;
    QStringList keyWords  = str.split(QString( " "));
    StandardItemModel : :ergodicAllItem(
        qobject_cast <QStandardItemModel * >(ui - >treeView - >model())
        ,std : :bind(callback_hightLightItem,std : :placeholders : :_1,keyWords)); //对于callback_hightLightItem是全局函数的情况下
}

由于回调函数是两个参数QStandardItem* item,const QStringList keys,而函数指针只是一个参数,因此需要绑定一个参数,使其变为参数只有一个的函数指针。这时就需要std::bind来实现。
占位符_1表示这个参数是对应的函数指针的第一个参数所在位置,如当前函数是:
bool callback_hightLightItem(QStandardItem* item,const QStringList keys);
我们要把他转换为如下类型的函数指针
bool(QStandardItem*)
第一个参数是正好对应,所以占位符_1就位于第一个位置,后面的参数直接传递进去就行。

如果回调写成:
bool callback_hightLightItem(const QStringList keys,QStandardItem* item);
那么写法变为:
std::bind(callback_hightLightItem,keyWords,std::placeholders::_1);
如果callback_hightLightItem是类成员函数,那么其写法如下
StandardItemModel : :ergodicAllItem(
        qobject_cast <QStandardItemModel * >(ui - >treeView - >model())
        ,std : :bind( &MainWindow : :callback_hightLightItem, this,std : :placeholders : :_1,keyWords));

bind也能轻松搞定类成员函数指针,注意要把类的指针传递过去。

© 著作权归作者所有

共有 人打赏支持
尘中远
粉丝 1
博文 26
码字总数 47436
作品 0
朝阳
程序员
PyQt5系列教程(30): 文本输入栏(QLineEdit)4

这期我们继续介绍一下文本输入栏(QLineEdit),我们已经介绍了其常用属性、信号、函数还有自定义密码输入框,今天是最后一章,文本框自动补全。 若我们想用到QLineEdit自动补全的功能,必须...

学点编程吧 ⋅ 03/02 ⋅ 0

c++11实现异步定时器

c++11提供了丰富的时间和线程操作函数,比如 std::this_thread::sleep, std::chrono::seconds等。可以利用这些来很方便的实现一个定时器。 实现 ifndef TIMERH define TIMERH include includ...

moki_oschina ⋅ 05/23 ⋅ 0

(转)现代C++函数式编程

本文转自:http://geek.csdn.net/news/detail/96636 {public: { 评论 添加评论 发布链接 发布图文 返回顶部 发布到 主题 发布 评论

wangxiaocvpr ⋅ 2016/08/22 ⋅ 0

使用C++11封装线程池ThreadPool

读本文之前,请务必阅读: 使用C++11的function/bind组件封装Thread以及回调函数的使用 Linux组件封装(五)一个生产者消费者问题示例 线程池本质上是一个生产者消费者模型,所以请熟悉这篇文...

inevermore ⋅ 2015/03/19 ⋅ 0

[转]想看懂WebRtc,你须知道的C++11新特性「lambda,std::function以及std:bind」

转自:只为那传说中美丽的草原 C++11 中增加了许多的新特性。 在本文中,我们来聊一下lambda表达式,闭包,std::function以及std::bind。 lambda 表达式 C++11中新增了lambda 表达式这一语言...

音视频直播技术专家 ⋅ 2017/11/09 ⋅ 0

c++11特性与cocos2d-x 3.0之std::bind与std::function

原文地址:http://www.cnblogs.com/slysky/p/3822640.html 作者:阳光下的蒲公英 c++11特性与cocos2d-x 3.0之std::bind与std::function 昨天同事让帮忙写一小功能,才发现cocos2d-x 3.0 和 ...

智捷课堂 ⋅ 2015/08/21 ⋅ 0

C++11实现跨平台线程池

生产者消费者 转自:http://www.cnblogs.com/sanjin/archive/2012/08/09/2629890.html std::conditionvariable的使用方法如下: ·当持有锁(mutex)之后,线程调用wait ·wait解开持有的互斥锁...

初雪之音 ⋅ 2016/03/19 ⋅ 0

C++11 FAQ中文版:std::function 和 std::bind

三2Year 2011陈 良乔C++11 FAQ std::function 和 std::bind 标准库函数bind()和function()定义于头文件中(该头文件还包括许多其他函数对象),用于处理函数及函数参数。bind()接受一个函数(...

长平狐 ⋅ 2013/01/11 ⋅ 0

学习jQuery必须知道的几种常用方法

jQuery事件处理 ready(fn) 代码: $(document).ready(function(){ // Your code here... }); 作用:它可以极大地提高web应用程序的响应速度。通过使用这个方法,可以在DOM载入就绪能够读取并...

长平狐 ⋅ 2012/09/06 ⋅ 0

Boost中的function和bind功能,实现Linux下线程类封装

最近在看陈硕的MUDUO网络通信库的过程中,发现作者大量使用了Boost::function以及Boost::bind功能,为了能够正常的学习作者的代码,决定先弄明白function以及bind的功能。 Boost::Function ...

西昆仑 ⋅ 2012/06/11 ⋅ 8

没有更多内容

加载失败,请刷新页面

加载更多

下一页

JEPLUS主从功能配置之主从布局的设置——JEPLUS软件快速开发平台

JEPLUS主从功能配置之主从布局的设置 主从功能配置成功之后就需要根据业务需求来调整主从功能的数据显示方式,不同的主从数据的显示可以达到不同的主从数据显示效果,今天这篇笔记就讲解一下...

JEPLUS ⋅ 3分钟前 ⋅ 0

如何利用极光推送的新功能玩转世界杯营销

四年一次的世界杯已经于6月14日开赛!对于app的运营人员而言,这场远在俄罗斯的绿茵征战绝不仅仅牵动着球迷们的心,更拨动着众多互联网企业运营人员的神经。在这场营销大战中,push显然是app...

极光推送 ⋅ 7分钟前 ⋅ 0

Spring Cloud构建微服务架构-Hystrix依赖隔离

依赖隔离 “舱壁模式”对于熟悉Docker的读者一定不陌生,Docker通过“舱壁模式”实现进程的隔离,使得容器与容器之间不会互相影响。而Hystrix则使用该模式实现线程池的隔离,它会为每一个Hys...

itcloud ⋅ 9分钟前 ⋅ 0

SpringCloud 微服务 (八) 统一配置中心 Config Server&Client

壹 Spring Cloud Config 统一配置中心,方便维护配置文件,对一些公司对数据库密码等敏感的信息,对普通开发人员不公开,放在运维人员手上,对配置作一个隔离作用,另外项目线上的配置改动都要重新...

___大侠 ⋅ 12分钟前 ⋅ 0

echarts轮播地图并结合鼠标浮动点击

直接上代码 timeId=setInterval(function () { if(count<11){ myChart.dispatchAction({ type: 'downplay', ......

莫西摩西 ⋅ 15分钟前 ⋅ 0

基于 HTML5 的工业互联网 3D 可视化应用

工业企业中生产线处于高速运转,由工业设备所产生、采集和处理的数据量远大于企业中计算机和人工产生的数据,生产线的高速运转则对数据的实时性要求也更高。破解这些大数据就是企业在新一轮制...

xhload3d ⋅ 18分钟前 ⋅ 0

Nging启动与停止bat

start_nginx.bat @echo off  f:  cd F:\server\nginx-1.13.6  echo "nginx is starting on port 80"  start "" "nginx.exe"  exit   stop_nginx.bat @echo off::windows ......

Jay丶 ⋅ 19分钟前 ⋅ 0

SuRF: 一个优化的 Fast Succinct Tries

作者:唐刘 在前一篇文章中,我简单介绍了 Succinct Data Structure,这里我们继续介绍 SuRF。 Fast Succinct Tries SuRF 的核心数据结构就是 Fast Succinct Tries(FST),一种空间节省,支...

TiDB ⋅ 24分钟前 ⋅ 0

Kubernetes(六) - Secret和私有仓库认证

对一个公司来说安全也是最为重要的因为可能一旦出现安全问题可能这个公司就完了,所以对密码管理是一个长久不变的话题,Kubernetes对密码管理提供了Secret组件进行管理,最终映射成环境变量,文件...

喵了_个咪 ⋅ 25分钟前 ⋅ 0

DevOps的三大原则

DevOps的出现有其必然性。在软件开发生命周期中,遇到了两次瓶颈。第一次瓶颈是在需求阶段和开发阶段之间,针对不断变化的需求,对软件开发者提出了高要求,后来出现了敏捷方法论,强调适应需...

inidcard ⋅ 26分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部