• QT tableview 实现千万数据加载,内存消耗小


    QT tableview 实现千万数据加载,内存消耗小


    最近在使用Dltview tool 观测MCU 的core 使用情况,发现DLTView tool 可以快速加载文件,tableview中显示的数据可以轻松达到千万级别


    标题DLTview 
     从任务管理器中可以看出内存消耗 才500M


    标题任务管理器
     因为自己之前开发的工具也有类似的功能,但是效果没有这个好,于是研究了一下工具的源码,按照源码中的方法自己实验了一下tableview的用法。

    实现这个功能的关键是要自己定义一个model 和tableview 空间关联上,在自定义的model中使用一个vector 的size 来记录 row 的大小。本例中使用QVector *indexAll

    #ifndef TABLEMODEL_H
    #define TABLEMODEL_H
     
    #include
    #include
     
    #include
    #include
     
     
    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 *pindexAll);
        void setHorizontalHeaderLabels(const QStringList &labels);
     
     
    private:
        QStringList headerList;
        QFile * pFile;
        QVector *indexAll;
    };
     
    #endif // TABLEMODEL_H
    #include "tablemodel.h"
    #include
     
     
     
    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()<< " "<  
         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 *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
    #include
    #include
     
     
    class WorkThread: public QThread
    {
    public:
        WorkThread(QFile * _pfile, QVector *pindexAll);
     
     
     
    protected:
        void run() override;
     
    private:
        QFile * pFile;
        QVector *indexAll;
     
     
    };
     
    #endif // WORKTHREAD_H
    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
     
    #include
    #include"tablemodel.h"
    #include
    #include
    #include"musicmodel.h"
    #include //定时器类
    #include
    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 indexAll;
       WorkThread * pThread;
     
       QTimer * timer;
    };
    #endif // MAINWINDOW_H
    #include "workthread.h"
    #include
    #include
    #include
    WorkThread::WorkThread(QFile * _pfile, QVector *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);
             //DU


             indexAll->push_back(i*4);//读到indexAll中
     
        }
        qDebug() << "The operation took" << timer.elapsed() << "milliseconds"; //显示结果
     
    }
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include"dltfileutils.h"
    #include
    #include
    #include
     
     
    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 :"<    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

  • 相关阅读:
    vue3 一个基于pinia简单易懂的系统权限管理实现方案,vue-router动态路由异步问题解决
    2023年11月25日小学生古诗文大会复选(复赛)答题操作手册
    vue(12)
    一文总结MySQL的指令是如何工作的
    IntelliJ IDEA Maven的详细安装教程(Windows版)(一站式:简介+下载+安装+环境搭建+IDEA上配置Maven)
    Linux搭建DNS服务
    Mysql 数据类型、运算符
    CSS相关
    C语言程序设计教程(第三版)李凤霞 第十章课后习题答案
    MySQL—MySQL的存储引擎之InnoDB
  • 原文地址:https://blog.csdn.net/lusic01/article/details/133674194