QTreeView处理大量数据(使用1000万条数据,每次都只是部分刷新)
如何使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万条数据,每次都只是部分刷新)的更多相关文章
- 绝对干货,教你4分钟插入1000万条数据到mysql数据库表,快快进来
		
我用到的数据库为,mysql数据库5.7版本的 1.首先自己准备好数据库表 其实我在插入1000万条数据的时候遇到了一些问题,现在先来解决他们,一开始我插入100万条数据时候报错,控制台的信息如下: ...
 - 1000万条数据导入mysql
		
今天需要将一个含有1000万条数据的文本内容插入到数据库表中,最初自然想到的是使用Insertinto '表名'values(),(),()...这种插入方式,但是发现这种方式对1000万条数据量的情 ...
 - 插入1000万条数据到mysql数据库表
		
转自:https://www.cnblogs.com/fanwencong/p/5765136.html 我用到的数据库为,mysql数据库5.7版本的 1.首先自己准备好数据库表 其实我在插入100 ...
 - Oracle 快速插入1000万条数据的实现方式
		
1.使用dual配合connect by level create table BigTable as select rownum as id from dual connect by level & ...
 - (C#版本)提升SQlite数据库效率——开启事务,极速插入数据,3秒100万,32秒1000万条数据
		
SQLite插入数据效率最快的方式就是:开启事务 + insert语句 + 关闭事务(提交) 利用事务的互斥性,如果在批量的插入操作前显式地开启一次事务,在插入操作结束后,提交事务,那么所有 ...
 - [C#]_[使用微软OpenXmlSDK (OpenXmlReader)读取xlsx表格] 读取大数据量100万条数据Excel文件解决方案
		
1.OpenXmlSDK是个很好的类库,可惜只能通过C#调用,C#的童鞋又福气了. 2.服务端程序由于没法安装office,所以这个对asp.net网站来说是最理想的库了.需要.net 4.0版本 ...
 - 极限挑战—C#+ODP 100万条数据导入Oracle数据库仅用不到1秒
		
链接地址:http://www.cnblogs.com/armyfai/p/4646213.html 要:在这里我们将看到的是C#中利用ODP实现在Oracle数据库中瞬间导入百万级数据,这对快速批量 ...
 - 使用hibernate在5秒内插入11万条数据,你觉得可能吗?
		
需求是这样的,需要查询某几个表的数据,然后插入到另外一个表. 一看到需求,很多人都会用hibernate去把这些数据都查询出来,然后放到list中, 然后再用for循环之类的进行遍历,一条一条的取出数 ...
 - (转)Python网络爬虫实战:世纪佳缘爬取近6万条数据
		
又是一年双十一了,不知道从什么时候开始,双十一从“光棍节”变成了“双十一购物狂欢节”,最后一个属于单身狗的节日也成功被攻陷,成为了情侣们送礼物秀恩爱的节日. 翻着安静到死寂的聊天列表,我忽然惊醒,不行 ...
 
随机推荐
- ecshop二次开发之购物车常见问题
			
1.ecshop二次开发中保存注册用户购物车数据解决方法:ecshop购物车是数据库中cart表来支持的,在ecshop表中rec_id是编号,user_id是注册用户的id,session_id表示 ...
 - MySQL AUTO_INCREMENT 简介
			
可使用复合索引在同一个数据表里创建多个相互独立的自增序列,具体做法是这样的:为数据表创建一个由多个数据列组成的PRIMARY KEY OR UNIQUE索引,并把AUTO_INCREMENT数据列包括 ...
 - JS中格式化数据保留两位小数
			
问题:在JS中格式化数据保留两位小数的函数的多种方法 最好方法: 保留两位好像是这样吧 var a = 9.39393; alert(a.toFixed(2)); 说明: ...
 - Ant Table组件
			
http://www.cnblogs.com/hujunzheng/p/5689650.html React中使用Ant Table组件 v一.Ant Design of React http:/ ...
 - MYSQL 引擎的情况
			
方法 1: show engine innodb status; ------------------------------------------------------------------- ...
 - Silverlight下的Socket通讯
			
http://www.cnblogs.com/chengxingliang/archive/2012/05/24/2515100.html 在Silverlight中进行通讯,只能使用4502-453 ...
 - 传智播客C/C++学院年薪24-50万招聘C/C++讲师
			
C/C++技术讲师 6名 (北京,年薪:24-50万) 传智播客C/C++课程培训体系如下: 1.C语言,世界五百强C语言面试训练 2.C++语言,世界五百强C++语言面试训练 3.数据结构与算法,世 ...
 - Mysql查询优化随笔记录
			
select SQL_CALC_FOUND_ROWS * from (select * from oses_vehdata201606 union all select * from oses_ ...
 - [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(一)
			
目的: 结合现在比较流行的技术,通过一个demo 展示一个全栈式设计的各种技能. 一个全栈式的工程师,应该能设计通过verilog/VHDL做logical设计.能写内核驱动,能架站. 要熟悉veri ...
 - 排序方法之标准库中的快排 qsort ()函数
			
C标准库qsort()函数的用法(快排) 使用快速排序例程进行排序 头文件:stdlib.h 用 法: void qsort(void *base, int nelem, int width, i ...