如何使QTreeView快速显示1000万条数据,并且内存占用量少呢?这个问题困扰我很久,在网上找了好多相关资料,都没有找到合理的解决方案,今天在这里把我的解决方案提供给朋友们,供大家相互学习。
我开始使用的QTreeWidget 控件来显示我的数据,发现该控件在显示10000行以下的数据还可以应付的过来,但超过10000条,就明显感觉到屏幕刷新就会有卡的现象,而且占据内存很大,虽然操作起来简单方便,但灵活性没有QTreeView强大。因为我要显示的数据量是非常大的,甚至过1000万,因此,采用QTreeWidget来显示,很显然不能满足性能要求,所以打算采用QTreeView来显示,不罗嗦了,赶快进入正题了,下面讲讲我是怎么通过QTreeView来快速显示1000万条数据的吧!
    1.通过从文件里面读取要显示的数据,交给QTreeView来显示,从而不用把数据一次性读到内存,就可以解决内存占用大的问题。
2.我们知道数据显示是通过刷新来实现的,通过刷新时,每次只刷新屏幕可见区域,其他部分不用刷新的方法,从而解决速度显示慢的问题。
解决了上面的两个问题,显示1亿条数据都不会有任何问题,而且显示速度和内存占有量与显示1000条数据相当,听起来很诱人啊,下面是我是怎么通过QTreeView来解决这两个问题的:
1.重载QAbstractItemModel中的如下函数:
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
QVariant data(const QModelIndex &index, int role) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const;
QModelIndex parent(const QModelIndex &index) const;
(1)QVariant headerData(intsection, Qt::Orientationorientation, int role =Qt::DisplayRole)const;显示树视的标题,section表示列,从0开始,orientation表示标题的方向(水平还是垂直),role表式标题栏显示的方式,当role的角色为Qt::DisplayRole时,表示显示文本,当然还有其他角色,大家可以参考Qt开发手册。示例代码:
QVariant CMyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
{
return pData->headerData(section);
}
return QVariant();
}
显示水平标题,其中pData是我定义的一个数据类的对象,在这里我把该类命名为CData。headerData来取出要显示的数据。
(2)QVariant data(const QModelIndex &index,int role)const;显示数据,index表示树节点索引,树中的每个节点都有一个对应的该索引,当index = QModelIndex()时,表示该节点是根节点,否则为非根节点。index中存放了该节点在同存节点中的位置信息(行和列),以及节点的特殊信息,如index.internalPointer(),这是一个指针,我们可以通过该指针保存我们想要的节点信息,角色同上。示例代码:
QVariant CMyModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
int row = index.row();
int col = index.column();
if(role == Qt::DisplayRole)
{
return pData->getData(row, col);
}
return QVariant();
}
通过getData来获取要显示的数据,该数据方在我们的文件里,每次只需要读取我们想要显示的数据,不需要把所有的数据都放到内存,从而节省了内存空间,这样就解决了上面讲的第一个问题。
(3)int rowCount(const QModelIndex &parent = QModelIndex())const;大家不难猜出该函数是返回该父节点下有多少个子节点,还是来看示例代码吧:
int CMyModel::rowCount(const QModelIndex &parent)const
{
return pData->rowCount();
}
为了简单起见,这里不考虑父节点,认为任何节点都存在rowCount()个节点。
(4)int columnCount(const QModelIndex &parent = QModelIndex())const;返回父节点有多少列,示例代码:
int CMyModel::columnCount(const QModelIndex &parent)const
{
return pData->colCount();
}
(5)接下来看QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;的实现:
QModelIndex CMChModel::index(int row, int column, const QModelIndex &parent) const
{
return createIndex(row, column, NULL);
}
通过该函数创建节点的索引,我这里简单一点,只创建一层节点,若大家要创建多层节点,则要通parent索引里的数据(如internalPointer())来创建对应的节点,通过createIndex的第3个参数来向节点传入指定的索引数据,由于我这里不需要创建多层节点,所以我传入NULL。那麽我们怎么建立节点的父子关系呢,聪明的你肯定想到了吧,QModelIndex parent(const QModelIndex &index) const;就是建立父子节点的父子关系的,如果只有一层节点,该函数无须重载,至此我们的显示数据模型已经实现了,接下来就是要把这个模型通过视图来表现出来(QTreeView)。
我们看看QTreeView是怎么来显示我们上面建立的模型的,看一段简单的代码,大家就明白了:
QTreeView treeView;
CMyModel *pModel = new CMyModel();
treeView.setModel(pModel);
treeView.show();
2.是不是很简单,到这里通过QTreeView来处理大量的数据的实现方式差不多讲完了,当你按照上面的方式准备处理你的大批量数据时,你就会发现显示10000行数据还是会卡,这是什么原因呢?其实这个也困扰我很久,网上也没有找到相关资料,没办法啊,只有啃QTreeView实现的源代码,实际上QTreeView确实是显示可见部分数据(每次显示1000行数据,按理论上来说1000行足以占据计算机屏幕,这样一来不管你数据量是多大,我始终只取1000行数据,所以1亿条数据与1000条数据显示速度是一样的,只要你一次只读出要显示的数据,内存占有量也是一样的),既然问题都解决了,那麽为什么还会有卡的现象呢?
经过进一步研究QTreeView源代码,最后发现耗时的地方是QTreeView第一次刷新的时候会计算每一行的行高,这样刷新时,就要遍历所有行数据,原来卡是出在这个地方啊,那麽应该怎么解决呢?实现方法很简单,就是上面的代码多加一行,treeView.setUniformRowHeights(true);这样一来就不会刷新计算所有行的行高了,至此用QTreeView显示大批量数据问题得到解决。
最后再补充一下,该实现方式可以适应其他QTableView, QListView等视图。

http://blog.csdn.net/rabinsong/article/details/8452946

QTreeView处理大量数据(使用1000万条数据,每次都只是部分刷新)的更多相关文章

  1. 绝对干货,教你4分钟插入1000万条数据到mysql数据库表,快快进来

    我用到的数据库为,mysql数据库5.7版本的 1.首先自己准备好数据库表 其实我在插入1000万条数据的时候遇到了一些问题,现在先来解决他们,一开始我插入100万条数据时候报错,控制台的信息如下: ...

  2. 1000万条数据导入mysql

    今天需要将一个含有1000万条数据的文本内容插入到数据库表中,最初自然想到的是使用Insertinto '表名'values(),(),()...这种插入方式,但是发现这种方式对1000万条数据量的情 ...

  3. 插入1000万条数据到mysql数据库表

    转自:https://www.cnblogs.com/fanwencong/p/5765136.html 我用到的数据库为,mysql数据库5.7版本的 1.首先自己准备好数据库表 其实我在插入100 ...

  4. Oracle 快速插入1000万条数据的实现方式

    1.使用dual配合connect by level create table BigTable as select rownum as id from dual connect by level & ...

  5. (C#版本)提升SQlite数据库效率——开启事务,极速插入数据,3秒100万,32秒1000万条数据

    SQLite插入数据效率最快的方式就是:开启事务  +   insert语句  +  关闭事务(提交) 利用事务的互斥性,如果在批量的插入操作前显式地开启一次事务,在插入操作结束后,提交事务,那么所有 ...

  6. [C#]_[使用微软OpenXmlSDK (OpenXmlReader)读取xlsx表格] 读取大数据量100万条数据Excel文件解决方案

      1.OpenXmlSDK是个很好的类库,可惜只能通过C#调用,C#的童鞋又福气了. 2.服务端程序由于没法安装office,所以这个对asp.net网站来说是最理想的库了.需要.net 4.0版本 ...

  7. 极限挑战—C#+ODP 100万条数据导入Oracle数据库仅用不到1秒

    链接地址:http://www.cnblogs.com/armyfai/p/4646213.html 要:在这里我们将看到的是C#中利用ODP实现在Oracle数据库中瞬间导入百万级数据,这对快速批量 ...

  8. 使用hibernate在5秒内插入11万条数据,你觉得可能吗?

    需求是这样的,需要查询某几个表的数据,然后插入到另外一个表. 一看到需求,很多人都会用hibernate去把这些数据都查询出来,然后放到list中, 然后再用for循环之类的进行遍历,一条一条的取出数 ...

  9. (转)Python网络爬虫实战:世纪佳缘爬取近6万条数据

    又是一年双十一了,不知道从什么时候开始,双十一从“光棍节”变成了“双十一购物狂欢节”,最后一个属于单身狗的节日也成功被攻陷,成为了情侣们送礼物秀恩爱的节日. 翻着安静到死寂的聊天列表,我忽然惊醒,不行 ...

随机推荐

  1. C++中重载、重写(覆盖)和隐藏的区别实例分析

    这篇文章主要介绍了C++中重载.重写(覆盖)和隐藏的区别,是C++面向对象程序设计非常重要的概念,需要的朋友可以参考下 本文实例讲述了C++中重载.重写(覆盖)和隐藏的区别,对于C++面向对象程序设计 ...

  2. Mongodb基础知识----Mongodb权威指南阅读

    文档是Mongodb中数据的基本单元,类型关系型数据库中的行,每个文档都有一个键值唯一的键_id.集合可以看做拥有动态模式的表. Mongodb一个实例可以拥有多个相互独立的数据库. Mongodb区 ...

  3. 深入A标签点击触发事件而不跳转的详解

    本文介绍下,当点击A标签时,触发事件但不跳转的实现方法,有需要的朋友参考下吧. 点击页面上的空链接,点击后页面自动刷新,并会定位到页面顶端. 不过,有时需要点击#页面但不作跳转,可以这样写: < ...

  4. python模块—urllib

    1. 网页操作 urllib.urlopen(url[,data[,proxies]]) 打开一个url,返回一个文件对象,然后可以进行类似文件对象操作 url:远程数据的路径,即网址 data:表示 ...

  5. Umbraco安装权限问题

    当安装或升级,甚至是使用Umbraco时,如果出现一些莫名其妙的问题. 估计都是权限出了问题,用心参考下文: https://our.umbraco.org/documentation/Getting ...

  6. 省去路由器,Windows 7 也能做无线AP

    电脑越来越白菜了,很多朋友家里已经有不少于二台电脑了.比方说一台笔记本一台台试机,哪么上网和联机的问题,随之而来了,二台电脑很多人可能会去买一个路由器,事实上,如果你其中一台有二个网卡一个有线一个无线 ...

  7. Qt中如何禁掉所有UI操作以及注意事项(处理各个widget的eventFilter这一层,但是感觉不好,为什么不使用QApplication呢)

    刚做完的一个项目,在测试时出现了一个问题:由于多线程的存在,当进行语音识别时:如果用户点击程序界面上的button或者其他接受点击事件后会发出信号的widget时,程序会crash ! 后来尝试着从多 ...

  8. 可以把一堆dll文件放到程序目录下的一个自建目录里面

    窦宁波大哥哥的那篇文章的这种写法还是很有参考价值的. QString strLibPath(QDir::toNativeSeparators(QApplication::applicationDirP ...

  9. 运行预构建 Linux 映像的 Windows Azure 虚拟机中的交换空间 – 第 1 部分

    本文章由 Azure CAT 团队的 Piyush Ranjan (MSFT) 撰写. 随着基础结构服务(虚拟机和虚拟网络)近期在 Windows Azure 上正式发布,越来越多的企业工作负荷正在向 ...

  10. 04737_C++程序设计_第7章_类模板与向量

    例7.1 使用类模板的实例. 例7.2 求4个数中最大值的类模板程序. #include <iostream> using namespace std; template <clas ...