当前位置:网站首页>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 .
边栏推荐
- [FPGA tutorial case 6] design and implementation of dual port RAM based on vivado core
- Mathematical knowledge: divisible number inclusion exclusion principle
- Arduino DY-SV17F自动语音播报
- Meibeer company is called "Manhattan Project", and its product name is related to the atomic bomb, which has caused dissatisfaction among Japanese netizens
- Learn the five skills you need to master in cloud computing application development
- QTableWidget懒加载剩内存,不卡!
- [untitled]
- Find a benchmark comrade in arms | a million level real-time data platform, which can be used for free for life
- 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)
猜你喜欢
wirehark数据分析与取证A.pacapng
MySQL - database query - basic query
MySQL基础用法02
一位苦逼程序员的找工作经历
Why is it not recommended to use BeanUtils in production?
Leetcode 6103 - minimum fraction to delete an edge from the tree
[技术发展-23]:DSP在未来融合网络中的应用
C application interface development foundation - form control (2) - MDI form
MySQL foundation 04 MySQL architecture
一比特苦逼程序員的找工作經曆
随机推荐
C#应用程序界面开发基础——窗体控制(4)——选择类控件
[Cao gongzatan] after working in goose factory for a year in 2021, some of my insights
Mathematical knowledge: Nim game game theory
MySQL --- 数据库查询 - 条件查询
Using tensorboard to visualize the model, data and training process
力扣 204. 计数质数
按键精灵打怪学习-多线程后台坐标识别
Give you an array numbers that may have duplicate element values. It was originally an array arranged in ascending order, and it was rotated once according to the above situation. Please return the sm
Now that the teenager has returned, the world's fireworks are the most soothing and ordinary people return to work~
Tp6 fast installation uses mongodb to add, delete, modify and check
【C语言】指针与数组笔试题详解
Leetcode 6103 - minimum fraction to delete an edge from the tree
uniapp组件-uni-notice-bar通告栏
Concise analysis of redis source code 11 - Main IO threads and redis 6.0 multi IO threads
The thread reuse problem of PageHelper using ThreadLocal, did you use it correctly?
数学知识:能被整除的数—容斥原理
[system analyst's road] Chapter V double disk software engineering (development model development method)
什么是调。调的故事
[my advanced journey of OpenGL learning] collation of Euler angle, rotation order, rotation matrix, quaternion and other knowledge
Excel calculates the difference between time and date and converts it into minutes