当前位置:网站首页>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 .
边栏推荐
- 看疫情之下服装企业如何顺势而为
- 2022 Jiangxi Provincial Safety Officer B certificate reexamination examination and Jiangxi Provincial Safety Officer B certificate simulation examination question bank
- [shutter] animation animation (shutter animation type | the core class of shutter animation)
- [self management] time, energy and habit management
- Button wizard play strange learning - automatic return to the city route judgment
- [Arduino experiment 17 L298N motor drive module]
- [androd] module dependency replacement of gradle's usage skills
- Using tensorboard to visualize the model, data and training process
- 产业互联网的产业范畴足够大 消费互联网时代仅是一个局限在互联网行业的存在
- Vim 9.0正式发布!新版脚本执行速度最高提升100倍
猜你喜欢
[interview question] 1369 when can't I use arrow function?
并发编程的三大核心问题 -《深入理解高并发编程》
MySQL - database query - condition query
给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。【剑指Offer】
Excel calculates the difference between time and date and converts it into minutes
Using tensorboard to visualize the model, data and training process
How is the mask effect achieved in the LPL ban/pick selection stage?
dotConnect for PostgreSQL数据提供程序
Telephone network problems
Soft exam information system project manager_ Real topic over the years_ Wrong question set in the second half of 2019_ Morning comprehensive knowledge question - Senior Information System Project Man
随机推荐
Mongodb common commands of mongodb series
并发编程的三大核心问题 -《深入理解高并发编程》
Matlab Doppler effect produces vibration signal and processing
The latest analysis of tool fitter (technician) in 2022 and the test questions and analysis of tool fitter (technician)
MySQL - database query - basic query
Niu Ke swipes questions and clocks in
Canvas drawing -- bingdd
[untitled]
如今少年已归来,人间烟火气最抚凡人心 复工了~
不登陆或者登录解决oracle数据库账号被锁定。
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
[androd] module dependency replacement of gradle's usage skills
High-Resolution Network (篇一):原理刨析
Using tensorboard to visualize the model, data and training process
Find a benchmark comrade in arms | a million level real-time data platform, which can be used for free for life
Mathematical knowledge: divisible number inclusion exclusion principle
數學知識:臺階-Nim遊戲—博弈論
Swiftui component Encyclopedia: using scenekit and swiftui to build interactive 3D pie charts (tutorial with source code)
Why can't the start method be called repeatedly? But the run method can?
Soft exam information system project manager_ Real topic over the years_ Wrong question set in the second half of 2019_ Morning comprehensive knowledge question - Senior Information System Project Man