qt之解决qtableview加载百万行数据卡顿问题

我们在使用qtableview的时候,加载100行的数据,你不会感到有任何卡顿,但是加载百万行的数据,你会感到界面已经卡死,我们来看下效果:
qt之解决qtableview加载百万行数据卡顿问题

这是我需要加载的一个文件,我们看,共有100万行左右的数据,我们来看下没有优化的写法,及运行时候的效果:
代码:

m_pTestView = new EP_TableView(this);
QStandardItemModel *model = new QStandardItemModel();
m_pTestView->setModel(model);

QVBoxLayout *mainLayout=new QVBoxLayout(this);
mainLayout->addWidget(m_pTestView);
mainLayout->setMargin(0);
mainLayout->setSpacing(0);
this->setLayout(mainLayout);
//加载数据
QFile file("C:/Users/dujia/Desktop/ReceiverTableData.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    int i=0;
    while (!file.atEnd()) {
        QString strLine=file.readLine();
        QStringList strList=strLine.split("&");
        model->setItem(i,0,new QStandardItem(strList[0]));
        model->setItem(i,1,new QStandardItem(strList[1]));
        model->setItem(i,2,new QStandardItem(strList[2]));
        model->setItem(i,3,new QStandardItem(strList[3]));
        model->setItem(i,4,new QStandardItem(strList[4]));
        model->setItem(i,5,new QStandardItem(strList[5]));
        model->setItem(i,6,new QStandardItem(strList[6]));
        model->setItem(i,7,new QStandardItem(strList[7]));
        model->setItem(i,8,new QStandardItem(strList[8]));
        model->setItem(i,9,new QStandardItem(strList[9]));
        model->setItem(i,10,new QStandardItem(strList[10]));
        i=i+1;
    }

效果:
qt之解决qtableview加载百万行数据卡顿问题
当我运行的时候,界面是直接卡死的,可以看到cpu的占用了也很高。

下面开始进行优化,使用多线程,在程序运行时,单独开出一条线程,用来对model数据的加载,
这样会解决卡顿问题,界面也不会迟迟不显示。

直接看代码:
自定义model类
.h

#ifndef STANDARDITEMMODEL_H
#define STANDARDITEMMODEL_H

#include <QObject>
#include <QStandardItemModel>

static const char* DefQSReceiverInfoTableSize[20][3] =
{
    {"ID" , "130", "0"},
    {"Line" , "110", "0"},
    {"Point" , "110", "0"},
    {"Index" , "60", "0"},
    {"Type" , "60", "0"},
    {"X" , "120", "0"},
    {"Y" , "120", "0"},
    {"Z" , "120", "0"},
    {"Lat.-084" , "180", "0"},
    {"Long.-084" , "180", "0"},
    {"Elav.-84" , "180", "0"},
    {"Status" , "100", "0"},
    {"Point Depth" , "120", "0"},
    {"Water Depth" , "120", "0"},
    {"Seis Datum" , "150", "0"},
    {" " , "150", "0"},
    {" " , "150", "0"},
    {" " , "150", "0"},
    {" " , "150", "0"}
};

class StandardItemModel : public QStandardItemModel
{
    Q_OBJECT
public:
    explicit StandardItemModel(QObject *parent = nullptr);
    ~StandardItemModel();
signals:

public slots:
    void CreateData(QString i_path);
};

#endif // STANDARDITEMMODEL_H

.cpp

#include "standarditemmodel.h"
#include <QFile>
#include <QElapsedTimer>
#include <qdebug.h>

StandardItemModel::StandardItemModel(QObject *parent) : QStandardItemModel(parent)
{
    this->setColumnCount(15);
    for(int i=0;i<15;i++)
    {
        this->setHeaderData(i, Qt::Horizontal, QString::fromLocal8Bit(DefQSReceiverInfoTableSize[i][0]));
    }
}

StandardItemModel::~StandardItemModel()
{

}
//这里用于动态加载数据
void StandardItemModel::CreateData(QString i_path)
{
    QFile file(i_path);
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
        return;

    int i=0;
    while (!file.atEnd()) {
        QString strLine=file.readLine();
        QStringList strList=strLine.split("&");
        this->setItem(i,0,new QStandardItem(strList[0]));
        this->setItem(i,1,new QStandardItem(strList[1]));
        this->setItem(i,2,new QStandardItem(strList[2]));
        this->setItem(i,3,new QStandardItem(strList[3]));
        this->setItem(i,4,new QStandardItem(strList[4]));
        this->setItem(i,5,new QStandardItem(strList[5]));
        this->setItem(i,6,new QStandardItem(strList[6]));
        this->setItem(i,7,new QStandardItem(strList[7]));
        this->setItem(i,8,new QStandardItem(strList[8]));
        this->setItem(i,9,new QStandardItem(strList[9]));
        this->setItem(i,10,new QStandardItem(strList[10]));
        i=i+1;
    }
    qDebug()<<"i::"<<i;

    qDebug()<<"this:::"<<this->rowCount();
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "ep_tableview.h"
#include <QTableWidget>
#include <QThread>




class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void Start();

signals:
    void startRunning(QString);

private:
    EP_TableView *m_pTestView=nullptr;
    QThread m_thread;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ep_tableview.h"
#include <QStandardItemModel>
#include <QFile>
#include <QVBoxLayout>
#include <QElapsedTimer>
#include <QDebug>
#include <QScrollBar>
#include <QHeaderView>
#include "standarditemmodel.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->resize(800,500);
    QFont textFont;
    textFont.setPointSize(12);
    textFont.setFamily("Microsoft YaHei");

    m_pTestView = new EP_TableView(this);
    //------------------------thread
    StandardItemModel *model = new StandardItemModel();
    model->moveToThread(&m_thread);
    connect(this,&Widget::startRunning,model,&StandardItemModel::CreateData);
    connect(&m_thread,&QThread::finished,model,&QObject::deleteLater);
    m_thread.start();
    //-----------------------

    m_pTestView->setFont(textFont);

    m_pTestView->setModel(model);

    QVBoxLayout *mainLayout=new QVBoxLayout(this);
    mainLayout->addWidget(m_pTestView);
    mainLayout->setMargin(0);
    mainLayout->setSpacing(0);
    this->setLayout(mainLayout);

//    QFile file("C:/Users/dujia/Desktop/ReceiverTableData.txt");
//    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
//        return;

//    int i=0;
//    while (!file.atEnd()) {
//        QString strLine=file.readLine();
//        QStringList strList=strLine.split("&");
//        model->setItem(i,0,new QStandardItem(strList[0]));
//        model->setItem(i,1,new QStandardItem(strList[1]));
//        model->setItem(i,2,new QStandardItem(strList[2]));
//        model->setItem(i,3,new QStandardItem(strList[3]));
//        model->setItem(i,4,new QStandardItem(strList[4]));
//        model->setItem(i,5,new QStandardItem(strList[5]));
//        model->setItem(i,6,new QStandardItem(strList[6]));
//        model->setItem(i,7,new QStandardItem(strList[7]));
//        model->setItem(i,8,new QStandardItem(strList[8]));
//        model->setItem(i,9,new QStandardItem(strList[9]));
//        model->setItem(i,10,new QStandardItem(strList[10]));
//        i=i+1;
//    }
}

Widget::~Widget()
{
    m_thread.quit();
    m_thread.wait();
}

void Widget::Start()
{
    emit startRunning("C:/Users/dujia/Desktop/ReceiverTableData.txt");
}


//数据文件的话自己随便一个就可以

看下优化后的运行:
qt之解决qtableview加载百万行数据卡顿问题
我们看到数据显示出来,并且在实时的的加载。

上一篇:关于让Bar保持相同的状态


下一篇:sessionStorage跨页面通信