当前位置:网站首页>Qtablewidget lazy load remaining memory, no card!
Qtablewidget lazy load remaining memory, no card!
2022-07-03 01:31:00 【kchmmd】
Preface
Use tables to load data , A small amount of data shows no abnormality , When the data is too large , In particular, some interfaces may be added to the table to refresh in real time, such as the progress bar , The final effect is very poor , Load card , Occupy memory .
therefore , The following summary and sharing is a lazy loading strategy .
Loading policy description
There are two main points :
1、 For situations that require real-time update loading , Every time you load data , Don't tune clearContents()、removeRow(int row) Wait for a way to empty new, But to reuse what was already done last time new Out of Item, Change its content to the latest
2、 Only load within the visible range of the interface Item, The specific amount of data only needs to be reflected by the value of the scroll bar , Every time you change the scroll bar , Then follow the above 1 To refresh Item The content of


Go straight to the code
The code structure 
mytablewidget.h
#ifndef MYTABLEWIDGET_H
#define MYTABLEWIDGET_H
#include <QTableWidget>
#include <QResizeEvent>
#include <QWheelEvent>
#include <QScrollBar>
#include <QProgressBar>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QMenu>
#include <QContextMenuEvent>
class TableWidget: public QTableWidget
{
public:
TableWidget(QWidget *parent = nullptr):QTableWidget(parent){
}
~TableWidget(){
}
protected:
void wheelEvent(QWheelEvent *event) override {
}// Shield the mouse pulley event
};
class MyTableWidget: public QWidget
{
public:
MyTableWidget(QWidget *parent = nullptr);
~MyTableWidget();
virtual void InitTable();
virtual void LoadTableWidget();
void UpdateView();
void SetMenu(QMenu* menu);
void SetItemText(int row, int colunm, QString str);
void SetItemProgress(int row, int colunm, double value, double total);
protected:
void wheelEvent(QWheelEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
private:
TableWidget* m_table;
QScrollBar *m_scrollBar;
int m_itemHeight;
int m_currentRow;
int m_dataCnt;
public:
//data
std::map<QString, double> m_mapData;//name boxOffice
QMenu* m_menu = nullptr;
};
#endif // MYTABLEWIDGET_H
mytablewidget.cpp
#include "mytablewidget.h"
MyTableWidget::MyTableWidget(QWidget *parent):QWidget(parent)
{
m_table = new TableWidget(this);
// Click the header to sort
// connect(m_table->horizontalHeader(),&QHeaderView::sectionClicked,this,[=](int colunm){
// m_table->sortItems(colunm,Qt::AscendingOrder);
// });
m_table->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);// Turn off scroll bar
QHBoxLayout* hbox =new QHBoxLayout(this);
hbox->setMargin(0);
hbox->setSpacing(0);
hbox->addWidget(m_table);
m_itemHeight = 20;
m_dataCnt = 0;
m_scrollBar = new QScrollBar(Qt::Vertical);
connect(m_scrollBar,&QScrollBar::valueChanged,this,[=](int value){
// qDebug()<<"value:"<<value;
LoadTableWidget();
});
hbox->addWidget(m_scrollBar);
InitTable();
LoadTableWidget();
}
MyTableWidget::~MyTableWidget()
{
}
void MyTableWidget::InitTable()
{
QStringList headList;
headList<<" Serial number "<<" The title of the film "<<" box office ( Ten thousand yuan )"<<" Box office share ";
m_table->setColumnCount(headList.length());
m_table->setHorizontalHeaderLabels(headList);
m_table->verticalHeader()->setVisible(false);// Hide line numbers
m_table->verticalHeader()->setDefaultSectionSize(m_itemHeight);// Default line height
m_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);// Automatically divide the width of each column
//m_table->horizontalHeader()->setMinimumSectionSize(100);// Default column width
m_table->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter);// Center the header
m_table->setSelectionBehavior(QAbstractItemView::SelectRows);// Select by behavior unit
m_table->setEditTriggers(QAbstractItemView::NoEditTriggers);// No editing
m_table->horizontalHeader()->setStyleSheet("QHeaderView::section{background-color:rgb(216,226,236);"
"border:0.5px solid rgb(254,254,254);}");
}
void MyTableWidget::SetItemText(int row, int colunm, QString str)
{
QTableWidgetItem* item = m_table->item(row, colunm);
if(nullptr == item)
{
item = new QTableWidgetItem;
m_table->setItem(row, colunm, item);
}
item->setText(str);
}
void MyTableWidget::SetItemProgress(int row, int colunm, double value, double total)
{
QWidget *widget = m_table->cellWidget(row, colunm);
QProgressBar* bar = static_cast<QProgressBar*>(widget);
if(nullptr == bar)
{
bar = new QProgressBar;
bar->setObjectName("progress");
m_table->setCellWidget(row, colunm, bar);// After setting, it will automatically show
bar->hide();// First hide After loading, it will automatically show
}
double percent =(double) value/total;
bar->setAlignment(Qt::AlignCenter);
bar->setRange(0,100);
bar->setValue(percent*100);
bar->setFormat(QString("%1%").arg(QString::number(percent*100,'f',1)));
}
void MyTableWidget::LoadTableWidget()
{
int oldRow = m_table->rowCount() - 1;
if(m_currentRow < oldRow)// If item If you have it, don't delete it and create it again , Before item Just change the content , Interface size changes , The displayed line changes , Delete more ,
for (int i=oldRow - 1; i>oldRow - m_currentRow - 1; i--)
{
m_table->removeRow(i);
}
m_table->setRowCount(m_currentRow+1);
int total = 1000;
std::map<QString, double>::iterator itor = m_mapData.begin();
int beginRow = m_scrollBar->value();// Scroll bar value , Table row
for (int i=0; i<beginRow; i++){
itor++;}// The corresponding display from the value of the scroll bar
for (int i =0 ; i<m_currentRow; i++,itor++)
{
if(itor == m_mapData.end())
{
m_table->removeRow(i);
break;
}
SetItemText(i, 0, QString::number(beginRow++));
SetItemText(i, 1, itor->first);
SetItemText(i, 2, QString::number(itor->second,'f',2));
SetItemProgress(i, 3, itor->second, total);
}
}
void MyTableWidget::UpdateView()
{
LoadTableWidget();
}
void MyTableWidget::SetMenu(QMenu *menu)
{
m_menu = menu;
}
void MyTableWidget::resizeEvent(QResizeEvent *event)
{
m_currentRow = height()/m_itemHeight;
m_dataCnt = m_mapData.size();
if(m_dataCnt - m_currentRow > 0)
{
m_scrollBar->setRange(0,m_dataCnt - m_currentRow + 2);
m_scrollBar->show();
}
else
{
m_scrollBar->setRange(0,0);
m_scrollBar->hide();
}
LoadTableWidget();
}
void MyTableWidget::contextMenuEvent(QContextMenuEvent *event)
{
QTableWidgetItem* item = m_table->itemAt(event->pos());
if(item && m_menu)
m_menu->exec(event->globalPos());
}
void MyTableWidget::wheelEvent(QWheelEvent *event)
{
int value = m_scrollBar->value();
if(event->delta() > 0)
{
value -= m_currentRow;
if(value < m_scrollBar->minimum())
value = m_scrollBar->minimum();
m_scrollBar->setValue(value);
}
else
{
value += m_currentRow;
if(value > m_scrollBar->maximum())
value = m_scrollBar->maximum();
m_scrollBar->setValue(value);
}
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "mytablewidget.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
QString GetStr();
private:
Ui::Widget *ui;
MyTableWidget* m_myTable;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QHBoxLayout>
#include <QTimer>
#include <QHeaderView>
#include <QProgressBar>
#include <QScrollBar>
#include <QActionGroup>
#include <QMessageBox>
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("TableWidget load - Dynamic loading - Load only the display area ");// Put it in ui->setupUi(this); After that, it won't work
qsrand(time(nullptr));
m_myTable=new MyTableWidget(this);
QHBoxLayout* hbox =new QHBoxLayout(this);
hbox->setMargin(0);
hbox->setSpacing(0);
hbox->addWidget(m_myTable);
int dataCnt = 134217;
for (int i=0; i<dataCnt;i++) {
double value = rand()%1000000+1000;
m_myTable->m_mapData[GetStr()] = value/100;
}
QMenu* menu = new QMenu(this);
connect(menu,&QMenu::triggered,this,[=](QAction* action){
QString str = action->text();
if("test_1" == action->text())
{
QMessageBox::information(nullptr,"Info","you choice test_1");
}
else if("test2" == action->text())
{
QMessageBox::information(nullptr,"Info","you choice test2");
}
else if("test1" == action->text())
{
QMessageBox::information(nullptr,"Info","you choice test1");
}
});
QMenu* menu_1 = new QMenu("test",this);
m_myTable->SetMenu(menu);
QAction *action_Desc = new QAction("test1");
QAction *action_Asce = new QAction("test2");
action_Desc->setCheckable(true);
action_Asce->setCheckable(true);
action_Asce->setChecked(true);
QActionGroup *group = new QActionGroup(this);
group->addAction(action_Asce);
group->addAction(action_Desc);
menu_1->addAction(action_Desc);
menu_1->addAction(action_Asce);
menu->addMenu(menu_1);
menu->addAction("test_1");
QTimer* m_timer = new QTimer(this);
connect(m_timer,&QTimer::timeout,this,[=]()mutable{
std::map<QString, double>::iterator itor = m_myTable->m_mapData.begin();
for (; itor!=m_myTable->m_mapData.end();itor++) {
double value = rand()%1000000+1000;
itor->second = value/100;
}
m_myTable->UpdateView();
});
m_timer->start(1000);
}
Widget::~Widget()
{
delete ui;
}
QString Widget::GetStr()
{
int length = rand()%15+5;
const char ch[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
int size = sizeof(ch);
char* str = new char[length + 1];
int num = 0;
int i;
for (i = 0; i < length; ++i)
{
num = rand() % (size - 1);
str[i] = ch[num];
}
str[i] = '\0';
QString res(str);
//return res;
return "《"+res+"》";
}
summary
If you are interested, you can compare , I share and normally load millions of levels of data into the table at a time , These two ways , Look at the program memory , And loading speed , Logic processing is still very fast , draw UI It's really slow , Occupy memory . Theoretically , The maximum size of data loaded by this strategy I share , It is mainly related to the data storage method and capacity , After all, the visual range of the loading interface Item It's still faster ., But for example, you use containers map There is still an upper limit to storage .
边栏推荐
- 数学知识:Nim游戏—博弈论
- 给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。【剑指Offer】
- 什么是调。调的故事
- Arduino dy-sv17f automatic voice broadcast
- 英语常用词汇
- [Cao gongzatan] after working in goose factory for a year in 2021, some of my insights
- 强化学习 Q-learning 实例详解
- [C language] detailed explanation of pointer and array written test questions
- C#应用程序界面开发基础——窗体控制(3)——文件类控件
- [Androd] Gradle 使用技巧之模块依赖替换
猜你喜欢

Detailed explanation of Q-learning examples of reinforcement learning

Cut point of undirected graph

Leetcode 6103 - minimum fraction to delete an edge from the tree

Force buckle 204 Count prime

How is the mask effect achieved in the LPL ban/pick selection stage?

Excel if formula determines whether the two columns are the same

【QT】自定义控件的封装

Find a benchmark comrade in arms | a million level real-time data platform, which can be used for free for life

看完这篇 教你玩转渗透测试靶机Vulnhub——DriftingBlues-9

dotConnect for PostgreSQL数据提供程序
随机推荐
Matlab Doppler effect produces vibration signal and processing
【面试题】1369- 什么时候不能使用箭头函数?
Kivy教程大全之如何在 Kivy 中创建下拉列表
d,ldc構建共享庫
[androd] module dependency replacement of gradle's usage skills
产业互联网的产业范畴足够大 消费互联网时代仅是一个局限在互联网行业的存在
Leetcode 2097 - Legal rearrangement of pairs
MySQL basics 03 introduction to MySQL types
Mathematical knowledge: divisible number inclusion exclusion principle
C#应用程序界面开发基础——窗体控制(4)——选择类控件
2022 Jiangxi Provincial Safety Officer B certificate reexamination examination and Jiangxi Provincial Safety Officer B certificate simulation examination question bank
Swiftui component Encyclopedia: using scenekit and swiftui to build interactive 3D pie charts (tutorial with source code)
QTableWidget懒加载剩内存,不卡!
Force buckle 204 Count prime
Look at how clothing enterprises take advantage of the epidemic
What are the trading forms of spot gold and what are the profitable advantages?
一位苦逼程序员的找工作经历
Button wizard play strange learning - automatic return to the city route judgment
【我的OpenGL学习进阶之旅】关于欧拉角、旋转顺序、旋转矩阵、四元数等知识的整理
力扣 204. 计数质数