原文链接:QRowTable表格控件(四)-效率优化之-优化数据源

一、开心一刻

一程序员第一次上女朋友家她妈板着脸问 :你想娶我女儿,有多少存款?

程序员低了下头:五百!

她妈更鄙视了:才五百块,买个厕所都不够!

程序员忙说:不是人民币!

她妈:就算是美元,还是不够买厕所!

程序员:其实是比特币!

她妈:哇,贤婿,我给你买只大龙虾去

二、问题分析

前边已经写了3篇关于表格控件的功能,分别是QRowTable表格控件-支持hover整行、checked整行、指定列排序等QRowTable表格控件(二)-红涨绿跌QRowTable表格控件(三)-效率优化之-合理使用QStandardItem,这三篇文章主要是围绕实现核心功能来讲述的一般实现方式,当数据量多大时就会出现性能问题。

既然出现问题,当然是需要解决的。本篇文章就来讲述怎么处理大量数据的情况。

首先我们先来分析下上述几种实现方式为什么会比较消耗时间,首先代码量也不大,在代码里随机打几个断点,我们就会发现,代码在循环构造QStandardItem这个结构中耗费的时间比较久,并且当for循环出现上万次循环时尤为明显。

找到问题后,就是想办法怎么可以更少的调用构造QStandardItem这个流程,当然了Qt也给我们提供了很好的解决方案,那就是重写数据源(Model)。

三、重写数据源

Qt中包含有经典的MVC模式,比如我们经常使用的QStandardItemModel、QTableView和QStyledItemDelegate,当我们要实现一个高效的表格控件时,重写这3个类基本就可以完成我们所需要的功能。

当然了Qt还提供了了一层数据缓存层QSortFilterProxyModel,这个类可以帮助我们更好的实现排序、模糊搜索功能

本篇文章这里只讲解重写数据源,关于其他两个类的重写前面文章中应该有所讲述,这里不再过多解释。

下面一起来看下数据源的重写方式,我们这里选择继承自QStandardItemModel这个类来实现我们的数据源,这里是一个偷懒的方式,正常情况下是需要重写QAbstractItemModel类,如果重写QAbstractItemModel类的话,那么就需要重写更多的接口。

class QRowModel : public QStandardItemModel
{
Q_OBJECT public:
explicit QRowModel(QObject * parent = 0);
~QRowModel();
public:
//设置数据源
void SetSourceData(const TradeOrderInfoList & data);
... protected:
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
virtual void sort(int column, Qt::SortOrder order /* = Qt::AscendingOrder */) override; private:
...
TradeOrderInfoList itemList;
QColor m_CheckedColor = QColor("#4F4F4F");
mutable std::map <int, int> m_AlignmentList;//列对其方式 friend class QRowTable;
};

上次代码是重写Model类的头文件,其中有一些不相干的代码我选择了隐藏,重写Model最重要的就是需要我们自己去存储数据,并且在Qt的调用机制调用获取数据时给他返回即可。

关键点

  1. 重写Model,自己存储数据
  2. 重写data接口,返回数据

1、自己存储数据

自己存储数据有一个好处,那就是我们在给Model设置数据时,最大的性能损耗就是数据拷贝的过程,仔细想想这个是不是都不是问题。

上述代码中的TradeOrderInfoList这个接口提就是我们自己定义的一个容器接口,方便存储我们的表格数据,当视图绘制时,会从这里拿数据。

2、重写data接口

数据已经准备完毕,接下里就是View如何优雅的拿到数据并绘制了,这里我们重点讲述怎么拿数据,如何绘制是QStyledItemDelegate这个类的事,感兴趣的可以自己研究研究。

仔细查看Model的版主文档们就会发现有一个data接口函数,他的声明可能像下面这样

QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;

们的任务就是重写这个接口,返回指定索引上的指定类型数据

  1. index:表格cell的索引,包含有行和列序号
  2. role:表格数据类型,每一个cell上都包含有一系列键值对,方便存储单元格上的各种数据,比如说前景色、背景色、字体、位置、高亮色、背景画刷等等。
QVariant QRowModel::data(const QModelIndex &index, int role) const
{
if (Qt::DecorationRole == role)
{
int r = index.row();
int c = index.column();
if (r >= itemList.size())
{
return "";
}
const TradeOrderInfo & info = itemList.at(r);
switch (c)
{
case 0:
return QPixmap(stock_helper::getCurrencyIcon(info.market, info.symbol).c_str());
default:
"";
break;
}
}
else if (Qt::ForegroundRole == role)
{
int r = index.row();
int c = index.column();
if (r >= itemList.size())
{
return "";
}
const TradeOrderInfo & info = itemList.at(r);
switch (c)
{
case 4://"方向"
if (info.action.compare("SELL") == 0)
{
return QColor("#218DF2");
}
else
{
return QColor("#FF4A4A");
}
default:
return QColor("#dddddd");
}
}
else if (Qt::DisplayRole == role)
{
//自己从model中拿数据给view
//"名称"
int r = index.row();
int c = index.column();
if (r >= itemList.size())
{
return "";
}
const TradeOrderInfo & info = itemList.at(r);
switch (c)
{
case 0://"名称"
return stock_helper::OrderDisplayName(&info);
case 1://"代码"
return stock_helper::OrderDisplaySymbol(&info, m_strAccount);
case 2://"成交量" 数字居右
return QString::number(info.totalQuantity);
case 3://"成交均价" 数字居右
return stock_helper::PriceDisplayName(info.symbol, info.market, info.secType, info.avgFillPrice);
case 4://"方向"
if (info.action.compare("SELL") == 0)
{
return QUI_LOAD_STRING(TTS_ORDER_DIR_SELL);
}
else
{
return QUI_LOAD_STRING(TTS_ORDER_DIR_BUY);
}
default:
"";
break;
}
} return QStandardItemModel::data(index, role);
}

别忘啦,当数据源发生变化的时候使用SetSourceData接口更新下。

数据源重写好以后,再试试我们的性能是不是杠杠滴。

四、比较

本篇文章应该是实现表格功能的最后一篇文章了,可以满足大多数的产品需求。

后续可能还会陆续出一些更友好的交互优化,敬请期待。

下面是一个表格,包含了传统的表格数据源和重写后的表格数据源优劣比较。

比较项目 传统方式 重写Model
难易程度 简单 复杂
代码里
性能
推荐度 两颗星 五颗星

五、相关文章

  1. Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等

  2. Qt高仿Excel表格组件-支持冻结列、冻结行、内容自适应和合并单元格

  3. 属性浏览器控件QtTreePropertyBrowser编译成动态库(设计师插件)

  4. 超级实用的属性浏览器控件--QtTreePropertyBrowser

  5. Qt之表格控件蚂蚁线

  6. QRowTable表格控件-支持hover整行、checked整行、指定列排序等

  7. QRowTable表格控件(二)-红涨绿跌

  8. QRowTable表格控件(三)-效率优化之-合理使用QStandardItem


值得一看的优秀文章:

  1. 财联社-产品展示
  2. 广联达-产品展示
  3. Qt定制控件列表
  4. 牛逼哄哄的Qt库
如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!!

很重要--转载声明

  1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords

  2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。


QRowTable表格控件(四)-效率优化之-优化数据源的更多相关文章

  1. QRowTable表格控件(三)-效率优化之-合理使用QStandardItem

    目录 一.开心一刻 二.概述 三.效果展示 四.QStandardItem 1.QStandardItem是什么鬼 2.性能分析 3.QStandardItem使用上的坑 五.相关文章 原文链接:QR ...

  2. QRowTable表格控件(五)-重写表头排序、支持第三次单击恢复默认排序

    目录 一.原生表格 二.效果展示 三.实现方式 1.排序列定制 2.排序交互修改 四.相关文章 原文链接:QRowTable表格控件(五)-重写表头排序.支持第三次单击恢复默认排序 一.原生表格 开发 ...

  3. QRowTable表格控件-支持hover整行、checked整行、指定列排序等

    目录 一.开心一刻 二.嘴一嘴 三.效果展示 四.浅谈实现 五.自定义数据源 1.data函数 2.flags函数 六.自定义视图 1.目的 2.问题分析 七.测试 八.相关文章 原文链接:QRowT ...

  4. QRowTable表格控件(二)-红涨绿跌

    目录 一.开心一刻 二.概述 三.效果展示 四.任务需求 五.指定列排序 六.排序 七.列对其方式 八.相关文章 原文链接:QRowTable表格控件(二)-红涨绿跌 一.开心一刻 一天,五娃和六娃去 ...

  5. QTableView表格控件区域选择-自绘选择区域

    目录 一.开心一刻 二.概述 三.效果展示 四.实现思路 1.绘制区域 2.绘制边框 3.绘制 五.相关文章 原文链接:QTableView表格控件区域选择-自绘选择区域 一.开心一刻 陪完客户回到家 ...

  6. Ext入门学习系列(五)表格控件(2)

    上节学习了Ext中表格控件,从创建,到定义数据源.绑定显示,大体明白了一个基本的表格控件是怎么实现的.而我们用表格控件多用于从各种数据源接收数据并显示出来,并不是写死的.本章我们就不同数据源的不同实现 ...

  7. 纯前端表格控件SpreadJS以专注业务、提升效率赢得用户与市场

    提起华为2012实验室,你可能有点陌生. 但你一定还对前段时间华为的那封<海思总裁致员工的一封信>记忆犹新,就在那篇饱含深情的信中,我们知道了华为为确保公司大部分产品的战略安全和连续供应, ...

  8. Qt之表格控件蚂蚁线

    一.蚂蚁线 摘自互动百科:在图像影像软件中表示选区的动态虚线,因为虚线闪烁的样子像是一群蚂蚁在跑,所以俗称蚂蚁线.在Poshop,After Effect等软件中比较常见. 背景:用过excel的同学 ...

  9. Qt实现表格控件-支持多级列表头、多级行表头、单元格合并、字体设置等

    目录 一.概述 二.效果展示 三.定制表头 1.重写数据源 2.重写QHeaderView 四.设置属性 五.相关文章 原文链接:Qt实现表格控件-支持多级列表头.多级行表头.单元格合并.字体设置等 ...

随机推荐

  1. JavaScript的event对象

    JavaScript的event对象中 event.target指代的是:触发事件的元素 event.currentTarget指代的是:事件绑定的元素 <!DOCTYPE html> & ...

  2. Hadoop单机、伪分布式、分布式集群搭建

    JDK安装 设置hostname [root@bigdata111 ~]# vi /etc/hostname 设置机器hosts [root@bigdata111 ~]# vi /etc/hosts ...

  3. 分析android studio的项目结构

    以最简单的工程为例子,工程名为随意乱打的Exp5,新建好工程后将项目结构模式换成android: 1.manifests AndroidManifest.xml:APP的配置信息 <?xml v ...

  4. cs231n---循环神经网络

    1 RNN介绍 (1)一对多,多对一,多对多的任务 传统的神经网络只能处理一对一的任务,而RNN可以处理一对多,多对一,多对多的任务: 其中,一些典型的应用如下: Image Captioning:i ...

  5. Mac 查找粘贴板记录

    0x00 大落 一件蛮坑爹的事情,复制了找了好久的内容合集,在回别人的信息的时候又进行了复制其他内容的操作,结果吾覆盖了的上一次复制的内容-- 于是开始找找 macOS 有没有粘贴板记录的东西,然后在 ...

  6. 扩展GroupBox控件

    1.GroupBox的边框颜色可以自行设置: 2.GroupBox可以设置边框的为圆角: 3.设置GroupBox标题在控件中的位置. 4.设置GroupBox标题的字体和颜色. 具体实现步骤Pane ...

  7. .NET Core下操作Git,自动提交代码到 GitHub

    .NET Core 3.0 预览版发布已经好些时日了,博客园也已将其用于生产环境中,可见 .NET Core 日趋成熟 回归正题,你想盖大楼吗?想 GitHub 首页一片绿吗?今天拿她玩玩自动化提交代 ...

  8. Hbase多版本(version)数据写入和读取

    1. 首先创建一个支持多版本的hbase表 create }   2.put几条测试数据 put ','f1:name','jack1' put ','f1:name','jack2' 3.读取多版本 ...

  9. HBase 系列(二)—— HBase 系统架构及数据结构

    一.基本概念 一个典型的 Hbase Table 表如下: 1.1 Row Key (行键) Row Key 是用来检索记录的主键.想要访问 HBase Table 中的数据,只有以下三种方式: 通过 ...

  10. Windows 10“数字权利激活”永久性激活!!!

    直接运行软件即可自动激活,等出现"激活成功"即可关闭软件. 注意事项: 激活软件不会帮你打开Windows update服务,如关闭系统自动更细服务的需要先启动服务. 可以在小娜搜 ...