当前位置: 首页 > news >正文

【Qt】大数据量表格刷新优化--只刷新可见区域

Qt大数据量表格刷新优化–只刷新可见区域

一、核心思想

当表格数据量过大(如 thousands 级行数)时,全量刷新会导致大量不必要的计算和 UI 绘制,引发界面卡顿。优化方案是:仅刷新用户当前可见的表格行,鼠标滚动时动态更新可见区域并刷新,减少资源消耗,提升响应速度。

二、实现原理

1. 关键前提:获取可见行范围

通过表格视图的可见区域坐标,计算出当前用户能看到的行索引范围(startRowendRow)。
getVisibleRowRange() 的实现逻辑:

  • 利用 viewport()->rect() 获取表格视图的可见区域(视图中实际显示的矩形区域);
  • 通过 rowAt(int y) 方法,根据可见区域的顶部(viewTop)和底部(viewBottom)坐标,计算出对应的行索引;
  • 边界处理:确保行索引在有效范围内(0rowCount()-1),无数据时返回无效值(-1,-1)。

2. 仅处理可见行数据

在刷新逻辑(如定时器 onRefreshTimer())中,只针对可见行范围(startRowendRow)进行数据处理:

  • 遍历可见行,收集每行所需的数据源信息;
  • 批量存储可见行的更新数据(QMap<QString, QVariant> updates),避免逐行更新的开销。

3. 批量更新 UI

收集完可见行的更新数据后,通过 batchUpdateData(updates) 一次性更新表格的可见行,减少 UI 刷新次数(单次刷新比多次逐行刷新更高效)。

4. 动态响应滚动事件

当鼠标滚动时,表格的可见区域会变化,getVisibleRowRange() 会自动计算出新的 startRowendRow,后续刷新逻辑自然会处理新的可见行,无需额外绑定滚动事件(因为 rowAt() 会实时反映滚动后的坐标对应的行)。

三、QTableWidget 的实现方法

QTableWidget 是 Qt 提供的现成表格组件,继承自 QTableView,可复用上述核心思想,实现步骤如下:

1. 获取可见行范围

QPair<int, int> getQTableWidgetVisibleRows(QTableWidget* tableWidget) {if (tableWidget->rowCount() == 0) {return {-1, -1}; // 无数据时返回无效范围}// 获取视图可见区域的顶部和底部坐标(相对于表格视图)QRect viewRect = tableWidget->viewport()->rect();int viewTop = viewRect.top();int viewBottom = viewRect.bottom();// 根据坐标计算可见行索引int startRow = tableWidget->rowAt(viewTop);int endRow = tableWidget->rowAt(viewBottom);// 边界处理:确保行索引有效startRow = qMax(0, startRow);endRow = qMin(tableWidget->rowCount() - 1, endRow);return {startRow, endRow};
}

2. 绑定刷新触发事件

需要在定时刷新滚动时触发可见行刷新:

  • 定时刷新:用 QTimer 定时调用刷新函数;
  • 滚动响应:监听表格的垂直滚动条事件(verticalScrollBar()->valueChanged),滚动时触发刷新。
// 初始化时绑定事件
QTimer* refreshTimer = new QTimer(this);
connect(refreshTimer, &QTimer::timeout, this, &MyWidget::refreshVisibleRows);
refreshTimer->start(100); // 100ms 刷新一次// 滚动时触发刷新
connect(tableWidget->verticalScrollBar(), &QScrollBar::valueChanged, this, &MyWidget::refreshVisibleRows);

3. 实现可见行刷新逻辑

void MyWidget::refreshVisibleRows() {QTableWidget* table = tableWidget;auto [startRow, endRow] = getQTableWidgetVisibleRows(table);if (startRow == -1) return; // 无可见行// 1. 批量收集可见行数据(从数据源获取)QMap<int, QMap<int, QVariant>> rowData; // 行号 -> {列号: 数据}for (int row = startRow; row <= endRow; ++row) {// 假设从数据源获取当前行各列数据(示例逻辑)for (int col = 0; col < table->columnCount(); ++col) {QString key = QString("row%1_col%2").arg(row).arg(col);QVariant data = getDataFromSource(key); // 自定义数据源获取函数rowData[row][col] = data;}}// 2. 批量更新可见行 UIfor (auto it = rowData.begin(); it != rowData.end(); ++it) {int row = it.key();auto& colData = it.value();for (auto colIt = colData.begin(); colIt != colData.end(); ++colIt) {int col = colIt.key();QVariant value = colIt.value();// 更新单元格(若单元格不存在则创建)QTableWidgetItem* item = table->item(row, col);if (!item) {item = new QTableWidgetItem();table->setItem(row, col, item);}item->setText(value.toString()); // 根据实际数据类型处理}}
}

四、优势总结

  1. 性能优化:减少无效计算和 UI 绘制,尤其在大数据量(万级以上行)时,显著降低卡顿;
  2. 动态响应:鼠标滚动时自动刷新新可见区域,保持用户体验流畅;
  3. 通用性:核心逻辑(获取可见区域 -> 处理可见行 -> 批量更新)适用于 QTableViewQTableWidget 及自定义表格组件。
http://www.dtcms.com/a/572911.html

相关文章:

  • 基于 React 的倒计时组件实现:暴露方法供父组件状态管理
  • 2.每日机器学习——张量(Tensors)
  • wordpress换php7出错内蒙古seo公司
  • 设计模式——桥接模式(bridge)
  • 阳光家园广州网站个人网站如何做即时支付
  • Arbess零基础学习 - 使用Arbess+GitLab实现.Net 项目构建/主机部署
  • 【数据结构】PriorityQueue优先队列:基于堆(heap)实现
  • PCB设计如何防止别人抄板?
  • macOS自定义安装PlatformIO Core
  • VSCode中Copilot的询问、编辑、代理有啥区别?
  • 二重积分器(Double Integrator)
  • APP与小程序分账系统是什么?资金管理新思路,合规高效分账
  • Hudi和Iceberg的Specification规范角度详细比较异同点
  • 临安网站建设杭州低价做网站
  • 肇庆市手机网站建设品牌专业做网站企业
  • 幂等性 VS 分布式锁:分布式系统一致性的两大护法 —— 从原理到实战的深度剖析
  • 初识DDD架构
  • 一次redis内存泄露故障分析
  • 计算机网络自顶向下方法32——网络层 网络层概述 转发和路由选择,数据平面和控制平面(传统方法,SDN方法) 网络服务模型
  • 深入理解MySQL_3 I/O成本
  • 哪个网站可以做验证码兼职gom传奇网站建设
  • 做网站一年能赚多少钱没有备案的网站怎么挂广告
  • vscode-ssh无法进入docker问题解决
  • iOS 应用网络权限弹窗的问题及解决方案
  • 使用 FastAPI 异步动态读取 Nacos 配置
  • 怀远做网站电话网站建设期末作业要求
  • Arbess零基础学习 - 使用Arbess+GitLab实现PHP项目构建/主机部署
  • CS144 Lab:Lab0
  • 总结做产品开发的一些通病
  • 稳定币市场格局重构:分发权正在成为新的护城河!