当前位置:网站首页>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 .
边栏推荐
- 软考信息系统项目管理师_历年真题_2019下半年错题集_上午综合知识题---软考高级之信息系统项目管理师053
- Button wizard play strange learning - automatic return to the city route judgment
- Excel removes the data after the decimal point and rounds the number
- 【我的OpenGL学习进阶之旅】关于欧拉角、旋转顺序、旋转矩阵、四元数等知识的整理
- Mathematical knowledge: divisible number inclusion exclusion principle
- Key wizard play strange learning - multithreaded background coordinate recognition
- High-Resolution Network (篇一):原理刨析
- How is the mask effect achieved in the LPL ban/pick selection stage?
- 强化学习 Q-learning 实例详解
- [system analyst's road] Chapter V double disk software engineering (development model development method)
猜你喜欢
High-Resolution Network (篇一):原理刨析
Meituan dynamic thread pool practice ideas, open source
[androd] module dependency replacement of gradle's usage skills
[Androd] Gradle 使用技巧之模块依赖替换
leetcode 2097 — 合法重新排列数对
【面试题】1369- 什么时候不能使用箭头函数?
MySQL基础用法02
MySQL - database query - basic query
[FPGA tutorial case 6] design and implementation of dual port RAM based on vivado core
【FH-GFSK】FH-GFSK信号分析与盲解调研究
随机推荐
C application interface development foundation - form control (2) - MDI form
英语常用词汇
传输层 TCP主要特点和TCP连接
How wide does the dual inline for bread board need?
Swiftui component Encyclopedia: using scenekit and swiftui to build interactive 3D pie charts (tutorial with source code)
【面试题】1369- 什么时候不能使用箭头函数?
【FPGA教程案例5】基于vivado核的ROM设计与实现
C application interface development foundation - form control (4) - selection control
Dotconnect for PostgreSQL data provider
C#应用程序界面开发基础——窗体控制(1)——Form窗体
Esp32 simple speed message test of ros2 (limit frequency)
Excel removes the data after the decimal point and rounds the number
产业互联网的产业范畴足够大 消费互联网时代仅是一个局限在互联网行业的存在
数学知识:Nim游戏—博弈论
leetcode刷题_两数之和 II - 输入有序数组
The difference between tail -f, tail -f and tail
软考信息系统项目管理师_历年真题_2019下半年错题集_上午综合知识题---软考高级之信息系统项目管理师053
wirehark数据分析与取证A.pacapng
[fh-gfsk] fh-gfsk signal analysis and blind demodulation research
Appuyez sur l'apprentissage de l'esprit de frappe - reconnaissance des coordonnées de fond multithreadées