QT tableview 实现千万数据加载,内存消耗小
最近在使用Dltview tool 观测MCU 的core 使用情况,发现DLTView tool 可以快速加载文件,tableview中显示的数据可以轻松达到千万级别
标题DLTview
从任务管理器中可以看出内存消耗 才500M
标题任务管理器
因为自己之前开发的工具也有类似的功能,但是效果没有这个好,于是研究了一下工具的源码,按照源码中的方法自己实验了一下tableview的用法。
实现这个功能的关键是要自己定义一个model 和tableview 空间关联上,在自定义的model中使用一个vector 的size 来记录 row 的大小。本例中使用QVector<qint64> *indexAll
#ifndef TABLEMODEL_H
#define TABLEMODEL_H
#include <QAbstractItemModel>
#include<QFile>
#include <QObject>
#include<QString>
class TableModel : public QAbstractTableModel
{
Q_OBJECT
public:
TableModel();
QVariant data(const QModelIndex &index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
void modelChanged();
void SetFile( QFile * _pfile, QVector<qint64> *pindexAll);
void setHorizontalHeaderLabels(const QStringList &labels);
private:
QStringList headerList;
QFile * pFile;
QVector<qint64> *indexAll;
};
#endif // TABLEMODEL_H
#include "tablemodel.h"
#include<QDebug>
TableModel::TableModel()
{
//headerList << tr("Name") << tr("Age") << tr("Gender");
pFile=nullptr;
}
QVariant TableModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() ||
(role != Qt::DisplayRole && role != Qt::EditRole)) {
return QVariant();
}
if (index.row() >= indexAll->size() && index.row()<0)
{
return QVariant();
}
//qDebug() << index.row()<< " "<<index.column();
long int filterposindex = 0;
filterposindex =index.row();
// qint64 positionForIndex=(*indexAll)[filterposindex];
// getmessage( index.row(), positionForIndex, &decodeflag, &msg, &lastmsg, pFile, &success);
switch(index.column())
{
case 0:
return QString("%L1").arg(filterposindex);
case 1:
return QString("%L1").arg((*indexAll)[filterposindex]);
case 2:
return QString("%L1").arg((*indexAll)[filterposindex]+1);
case 3:
return QString("%L1").arg((*indexAll)[filterposindex]+2);
}
return QVariant();
}
QVariant TableModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if (orientation == Qt::Horizontal) { //水平表头
if (role == Qt::DisplayRole) { //角色为显示
return headerList.at(section); //返回指定位置表头
}
}
return QAbstractTableModel::headerData(section, orientation, role);
}
int TableModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return 0;
} else {
return indexAll->size(); //显示数据的大小
}
}
int TableModel::columnCount(const QModelIndex &parent ) const
{
if (parent.isValid()) {
return 0;
} else {
return headerList.size(); //表头的大小
}
}
void TableModel::modelChanged()
{
index(0, 1);
index(0, 0);
index(0, columnCount() - 1);
emit(layoutChanged());
}
void TableModel::SetFile( QFile * _pfile,QVector<qint64> *pindexAll)
{
pFile=_pfile;
indexAll=pindexAll;
}
void TableModel::setHorizontalHeaderLabels(const QStringList &labels) {
// qDebug() << PRETTY_FUNCTION;
if (!labels.empty())
headerList = labels;
}
#ifndef WORKTHREAD_H
#define WORKTHREAD_H
#include<QThread>
#include<QFile>
#include<QVector>
class WorkThread: public QThread
{
public:
WorkThread(QFile * _pfile, QVector<qint64> *pindexAll);
protected:
void run() override;
private:
QFile * pFile;
QVector<qint64> *indexAll;
};
#endif // WORKTHREAD_H
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include"tablemodel.h"
#include<QFile>
#include<QLabel>
#include"musicmodel.h"
#include <QTimer> //定时器类
#include<workthread.h>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_2_clicked();
void on_CreateData_clicked();
void on_actionLoadFile_triggered();
private:
Ui::MainWindow *ui;
TableModel * tableModel;
QFile outputfile;
QLabel *statusFilename;
QVector<qint64> indexAll;
WorkThread * pThread;
QTimer * timer;
};
#endif // MAINWINDOW_H
#include "workthread.h"
#include<QTime>
#include<QDebug>
#include <QtCore/QElapsedTimer>
WorkThread::WorkThread(QFile * _pfile, QVector<qint64> *pindexAll):pFile(_pfile),indexAll(pindexAll)
{
}
void WorkThread::run()
{
QElapsedTimer timer; //定义对象
timer.start(); //开始计时
for (int i = 0; i <10000000; i++)
{
QByteArray ba;
ba.resize(4);
ba[0] = (uchar)(0x000000ff & i);
ba[1] = (uchar)((0x0000ff00&i)>>8);
ba[2] = (uchar)((0x00ff0000&i)>>16);
ba[3] = (uchar)((0xff000000&i)>>24);
indexAll->push_back(i*4);
}
qDebug() << "The operation took" << timer.elapsed() << "milliseconds"; //显示结果
}
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include"dltfileutils.h"
#include<QDebug>
#include<QFileDialog>
#include <windows.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
statusFilename=new QLabel("No log file loaded");
statusFilename->setMinimumWidth(statusFilename->width());
//statusFilename->setMaximumWidth(statusFilename->width());
statusFilename->setMaximumWidth(1240);
// 640 is the initial width of the label
// but for some reason we need this for the very
// first call when setting the tempfile string
// unless this there are is displayed "..."
// more propper solution appreciated ...
statusFilename->setWordWrap(true);
statusBar()->addWidget(statusFilename,1);
QString fn = DltFileUtils::createTempFile(QDir ("."), false);
statusFilename->setText(fn);
statusFilename->setToolTip(fn);
outputfile.setFileName(fn);
outputfile.open(QIODevice::ReadWrite|QIODevice::Truncate);
tableModel =new TableModel;
tableModel->SetFile(&outputfile,&indexAll);
QStringList headerList;
headerList << tr("index") << tr("item1") << tr("item2")<< tr("item3")<< tr("item4");;
tableModel->setHorizontalHeaderLabels(headerList);
ui->tableView_3->setModel(tableModel);
ui->tableView_3->setSelectionBehavior(QAbstractItemView::SelectRows);
// ui->tableView_3->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableView_3->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableView_3->setStyleSheet("QHeaderView::section { background:green; color:white;min-height:3em;}");
ui->tableView_3->setGridStyle(Qt::SolidLine);
ui->tableView_3->horizontalHeader()->setStretchLastSection(true);
// ui->tableView_3->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableView_3->verticalHeader()->setVisible(false);
timer = new QTimer(this);
//启动定时器
// timer->setSingleShot (true);
connect(timer,&QTimer::timeout,[=](){
tableModel->modelChanged();
// ui->tableView_3->scrollToBottom();
});
pThread = new WorkThread(&outputfile,&indexAll);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_2_clicked()
{
// tableModel->removeColumns(0,1);
//tableModel->modelChanged();
}
void MainWindow::on_CreateData_clicked()
{
pThread->start();
// outputfile.close();
// qDebug()<<"size :"<<indexAll.size();
Sleep(100);
if(!timer->isActive())
timer->start(50);
}
void MainWindow::on_actionLoadFile_triggered()
{
QStringList fileNames = QFileDialog::getOpenFileNames(this,
tr("Open one or more DLT Log files"), "", tr("DLT Files (*.dlt);;All files (*.*)"));
if(fileNames.isEmpty())
return;
}
从log中看出来生成1千万数据耗时481毫秒
内存消耗186M
版权声明:本文为CSDN博主「cwei231」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cwei231/article/details/131947874