以前一直使用qtableiwdget,最近有时间来研究下qtableview,才知道,qtableview和自定义model,比qtablewidget的性能啊,及占用内存啊,优化太多了。以前我使用qtablewidget是进行动态加载,也可以对内存进行优化,但是前提是,你只看数据,不对数据进行操作。
先看一张对比图。我打开了大概10万条数据。
qtablewidget

可以看到占用内存400mb左右,操作起来轻微卡顿。我试过加载100万条数据,加载时候要等上几分钟,然后操作就卡的要死,内存爆到2个多g

然后看下qtableview和自定义model。

内存已经降到123mb,这个优化基本在1.5倍左右,加载100万数据的时候,大概占用750mb左右,操作流畅。

下面直接看model
qtableview使用自定义的model,需要继承QAbstractTableModel,需要实现3个纯虚函数rowcount,columncount,data,这3个是必须的。其他的纯虚函数根据需要进行实现,我是实现了删除功能(全选删除,按住ctrl删除),获取数据功能,以及设置数据功能。根据自己需求来吧,目前我只需要这么多。
直接看model代码吧

#ifndef MYTABLEMODEL_H
#define MYTABLEMODEL_H#include <QWidget>
#include <QAbstractTableModel>struct ModelItem {QString id;QString name;QString one;QString two;QString three;QString four;QString five;QString six;
};class MyTableModel : public QAbstractTableModel
{Q_OBJECT
public:explicit MyTableModel(QObject *parent = nullptr);~MyTableModel();int rowCount(const QModelIndex &parent = QModelIndex())const override;int columnCount(const QModelIndex &parent = QModelIndex())const override;QVariant data(const QModelIndex &index, int role = Qt::DisplayRole)const override;QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);//bool insertRows(int row, int count,const QModelIndex &parent = QModelIndex());virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());void SetDeleteList(QList<int> i_List);void SetHeadData(QStringList i_list);void SetModelData(QList<ModelItem> model);signals:private:QList<ModelItem> modelData;QStringList headeList;QList<int> m_DeleteList;};#endif // MYTABLEMODEL_H
#include "mytablemodel.h"
#include <qdebug.h>
#include <QElapsedTimer>MyTableModel::MyTableModel(QObject *parent)
{}MyTableModel::~MyTableModel()
{}int MyTableModel::rowCount(const QModelIndex &parent) const
{return modelData.count();
}int MyTableModel::columnCount(const QModelIndex &parent) const
{return headeList.size();
}QVariant MyTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{if (role == Qt::DisplayRole && orientation == Qt::Horizontal){if (section < headeList.size()){return headeList[section];}}return QAbstractItemModel::headerData(section, orientation, role);
}bool MyTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{if(!index.isValid())return 0;if(role == Qt::DisplayRole || role == Qt::EditRole){const int row=index.row();switch(index.column()){case 0: modelData[row].id=value.toString();break;case 1:modelData[row].name=value.toString();break;case 2:modelData[row].one=value.toString();break;case 3:modelData[row].two=value.toString();break;case 4:modelData[row].three=value.toString();break;case 5:modelData[row].four=value.toString();break;case 6:modelData[row].five=value.toString();break;case 7:modelData[row].six=value.toString();break;}emit dataChanged(index, index, QVector<int>() << role);return true;}return false;
}//bool MyTableModel::insertRows(int row, int count,const QModelIndex &parent)
//{    if(row<0||count<1||row>rowCount())
           return false;
       //需要将操作放到beginInsertRows和endInsertRows两个函数调用之间
       beginInsertRows(parent, row, row + count - 1);
       for(int i=row;i<row+count;i++)
       {           //在接口对应行插入空数据
           modelData.insert(i,ModelItem);
       }
       endInsertRows();
//    //       return true;
//}bool MyTableModel::removeRows(int row, int count, const QModelIndex &parent)
{if(row<0||count<1||row+count>rowCount())return false;//需要将操作放到beginRemoveRows和endRemoveRows两个函数调用之间beginRemoveRows(parent, row, row + count - 1);if(m_DeleteList.size()!=0){for(int i=0;i<m_DeleteList.size();i++){modelData.removeAt(m_DeleteList[i]);}}//    for(int i=row+count-1;i>=row;i--)
//    {//        //移除该行数据
//        modelData.removeAt(i);
//    }m_DeleteList.clear();endRemoveRows();return true;
}void MyTableModel::SetDeleteList(QList<int> i_List)
{m_DeleteList=i_List;
}QVariant MyTableModel::data(const QModelIndex &index, int role) const
{if(!index.isValid())return QVariant();if(role == Qt::DisplayRole || role == Qt::EditRole){const int row=index.row();switch(index.column()){case 0: return modelData.at(row).id;case 1:return modelData.at(row).name;case 2:return modelData.at(row).one;case 3:return modelData.at(row).two;case 4:return modelData.at(row).three;case 5:return modelData.at(row).four;case 6:return modelData.at(row).five;case 7:return modelData.at(row).six;}}return QVariant();
}void MyTableModel::SetHeadData(QStringList i_list)
{headeList=i_list;
}void MyTableModel::SetModelData(QList<ModelItem> model)
{modelData=model;
}

widget

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTableView>
#include "mytablemodel.h"
#include <QMenu>class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();void InitViewAction();public slots:void onShotListContextMenuClicked();void onImportTriggered();void onDeleteTriggered();void onDeleteALLTriggered();private:QTableView *m_pTableView=nullptr;MyTableModel *m_pModel=nullptr;QMenu *m_pMenu=nullptr;
};
#endif // WIDGET_H
#include "widget.h"
#include <qgridlayout.h>
#include <QStandardItemModel>
#include <qdebug.h>
#include <QTableWidget>
#include <qfile.h>
#include <QAction>
#include <qmenu.h>
#include <QHeaderView>
Widget::Widget(QWidget *parent): QWidget(parent)
{this->resize(800,500);m_pTableView=new QTableView(this);QVBoxLayout *mainLayout=new QVBoxLayout(this);mainLayout->addWidget(m_pTableView);mainLayout->setMargin(0);mainLayout->setSpacing(0);this->setLayout(mainLayout);InitViewAction();m_pTableView->setSelectionBehavior(QAbstractItemView::SelectRows);  //选中整行//m_pTableView->setContextMenuPolicy(Qt::ActionsContextMenu);m_pTableView->setContextMenuPolicy(Qt::CustomContextMenu);connect(m_pTableView, &QTableView::customContextMenuRequested, this, &Widget::onShotListContextMenuClicked);QStringList strList;strList<<QString("ID")<<"Name"<<"one"<<"two"<<"three"<<"four"<<"five"<<"six";m_pModel=new MyTableModel();m_pModel->SetHeadData(strList);m_pTableView->setModel(m_pModel);m_pTableView->verticalHeader()->hide();QList<ModelItem> modelData;QFile file("C:/Users/dujia/Desktop/bbb.txt");if (!file.open(QIODevice::ReadOnly | QIODevice::Text))return;while (!file.atEnd()) {QString strLine=file.readLine();QStringList strList=strLine.split("&");if(strList.size()<7){continue;}ModelItem item;item.id=strList[0];item.name=strList[1];item.one=strList[2];item.two=strList[3];item.three=strList[4];item.four=strList[5];item.five=strList[6];item.six="";modelData.append(item);}m_pModel->SetModelData(modelData);//    QTableWidget *widget=new QTableWidget(this);
//    //widget->setRowCount(1000000);
//    widget->setColumnCount(8);
//    QStringList strList;
//    strList<<QString("ID")<<"Name"<<"one"<<"two"<<"three"<<"four"<<"five";
//    widget->setHorizontalHeaderLabels(strList);
//    QVBoxLayout *mainLayout=new QVBoxLayout(this);
//    mainLayout->addWidget(widget);
//    mainLayout->setMargin(0);
//    mainLayout->setSpacing(0);
//    this->setLayout(mainLayout);//    QFile file("C:/Users/dujia/Desktop/bbb.txt");
//    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
//        return;
//    int i=0;
//    widget->setRowCount(100000);
//    while (!file.atEnd()) {//        QString strLine=file.readLine();
//        QStringList strList=strLine.split("&");
//        if(strList.size()<8)
//        {//            continue;
//        }
//        widget->setItem(i,0,new QTableWidgetItem(strList[0]));
//        widget->setItem(i,1,new QTableWidgetItem(strList[1]));
//        widget->setItem(i,2,new QTableWidgetItem(strList[2]));
//        widget->setItem(i,3,new QTableWidgetItem(strList[3]));
//        widget->setItem(i,4,new QTableWidgetItem(strList[4]));
//        widget->setItem(i,5,new QTableWidgetItem(strList[5]));
//        widget->setItem(i,6,new QTableWidgetItem(strList[6]));
//        widget->setItem(i,7,new QTableWidgetItem(strList[7]));//        i++;//    }
}Widget::~Widget()
{}void Widget::InitViewAction()
{m_pMenu = new QMenu(this);QAction *qcOnlyAction = new QAction(tr("QC only"), this);QAction *submitJobAction = new QAction(tr("Generate SEGD"), this);//QAction *killAllJobAction = new QAction(tr("Kill all jobs"), this);QAction *commentsAction = new QAction(tr("Comments..."), this);QAction *deleteAction = new QAction(tr("Delete..."), this);QAction *importAction = new QAction(tr("Import Shot Data"), this);QAction *allAction = new QAction(tr("All"), this);QAction *returnAction = new QAction(tr("Return"), this);m_pMenu->addSeparator();m_pMenu->addAction(importAction);m_pMenu->addSeparator();m_pMenu->addAction(qcOnlyAction);m_pMenu->addAction(submitJobAction);m_pMenu->addSeparator();m_pMenu->addSeparator();m_pMenu->addAction(deleteAction);m_pMenu->addSeparator();m_pMenu->addAction(allAction);m_pMenu->addAction(returnAction);m_pMenu->addSeparator();m_pMenu->addAction(commentsAction);m_pMenu->addSeparator();m_pMenu->hide();connect(importAction,&QAction::triggered,this,&Widget::onImportTriggered);connect(deleteAction,&QAction::triggered,this,&Widget::onDeleteTriggered);connect(allAction,&QAction::triggered,this,&Widget::onDeleteALLTriggered);}void Widget::onShotListContextMenuClicked()
{m_pMenu->move(QCursor::pos());m_pMenu->show();
}void Widget::onImportTriggered()
{QItemSelectionModel *selections =  m_pTableView->selectionModel();QModelIndexList selected = selections->selectedIndexes();QList<int> rowList;QMap<int, int> rowMap;foreach (QModelIndex index, selected){rowMap.insert(index.row(), 0);}int rowToDel;QMapIterator<int, int> rowMapIterator(rowMap);while (rowMapIterator.hasNext()){rowMapIterator.next();rowToDel = rowMapIterator.key();QModelIndex indexsix = m_pModel->index(rowToDel,7);m_pModel->setData(indexsix,"hello");}
}
#include <QElapsedTimer>
void Widget::onDeleteTriggered()
{QItemSelectionModel *selections =  m_pTableView->selectionModel();QModelIndexList selected = selections->selectedIndexes();QList<int> rowList;QMap<int, int> rowMap;foreach (QModelIndex index, selected){rowMap.insert(index.row(), 0);}int rowToDel;QMapIterator<int, int> rowMapIterator(rowMap);rowMapIterator.toBack();  //将迭代器移动到最后while (rowMapIterator.hasPrevious()){rowMapIterator.previous();rowToDel = rowMapIterator.key();rowList.append(rowToDel);}m_pModel->SetDeleteList(rowList);  //传入需要删除的数组m_pModel->removeRows(rowList.last(),rowList.size());m_pTableView->setCurrentIndex(QModelIndex());  //设置当前项为不存在的项,则为不选中
}void Widget::onDeleteALLTriggered()
{int count=m_pModel->rowCount();m_pModel->removeRows(0,count);
}

数据:

1512058602&   2884.00&  12010.00  &1&G1& 644347.8& 4229422.2&3123.7&38 12 04.281 N&076 38 54.825 E&3123.70&    &    &&
1512058603&   2884.00&  12011.00  &1&G1& 644357.8& 4229439.4&3123.8&38 12 04.833 N&076 38 55.249 E&3123.80&    &    &&
1512058604&   2884.00&  12012.00  &1&G1& 644367.7& 4229456.9&3123.1&38 12 05.395 N&076 38 55.669 E&3123.10&    &    &&
1512058605&   2884.00&  12013.00  &1&G1& 644377.8& 4229474.1&3124.3&38 12 05.947 N&076 38 56.096 E&3124.30&    &    &&

拿过去直接复制粘贴到txt就行了。
ヾ( ̄▽ ̄)ByeBye

qtableview及自定义model的使用,对比qtablewidget性能及内存优化相关推荐

  1. QTableView使用自定义委托(QItemDelegate)

    QTableView使用自定义委托(QItemDelegate) 需要在表格中绘制流程图,主要有箭头,方向,颜色,字符串,由于QTableView没有可用的绘制函数,所以需要自己去定义. 委托(del ...

  2. 什么是php model类,thinkphp的自定义model类有什么作用?

    请问,thinkphp的自定义model类有什么作用?如: <?php //自定义Modle类 namespace Home\Model; use Think\Model; class StuM ...

  3. [golang gin框架] 4.自定义Model以及Gin 文件上传

    一.Gin 中自定义 Model 关于 Model 如果应用非常简单的话,我们可以在 Controller 里面处理常见的业务逻辑,但是如果 有一个功能想在多个控制器.或者多个模板里面复用的话,那么就 ...

  4. ML之DTRFRExtraTRGBR:基于四种算法(DT、RFR、ExtraTR、GBR)对Boston(波士顿房价)数据集(506,13+1)进行价格回归预测并对比各自性能

    ML之DT&RFR&ExtraTR&GBR:基于四种算法(DT.RFR.ExtraTR.GBR)对Boston(波士顿房价)数据集(506,13+1)进行价格回归预测并对比各自 ...

  5. 【Android 内存优化】自定义组件长图组件 ( 长图滚动区域解码 | 手势识别 GestureDetector | 滑动计算类 Scroller | 代码示例 )

    文章目录 一.GestureDetector 创建与设置 二.GestureDetector 触摸事件传递 三.触摸滑动操作 四.惯性滑动操作 五.长图滑动组件代码示例 六.运行效果 七.源码及资源下 ...

  6. 【Android 内存优化】自定义组件长图组件 ( 获取图像宽高 | 计算解码区域 | 设置图像解码属性 复用 像素格式 | 图像绘制 )

    文章目录 一.获取图像真实宽高 二.计算解码区域 三.设置解码参数 内存复用 像素格式 四.图像绘制 五.执行效果 六.源码及资源下载 官方文档 API : BitmapRegionDecoder 在 ...

  7. ML之kNN(两种):基于两种kNN(平均回归、加权回归)对Boston(波士顿房价)数据集(506,13+1)进行价格回归预测并对比各自性能

    ML之kNN(两种):基于两种kNN(平均回归.加权回归)对Boston(波士顿房价)数据集(506,13+1)进行价格回归预测并对比各自性能 目录 输出结果 设计思路 核心代码 输出结果 Bosto ...

  8. ML之SVM(三种):基于三种SVM(linearSVR、polySVR、RBFSVR)对Boston(波士顿房价)数据集(506,13+1)进行价格回归预测并对比各自性能

    ML之SVM(三种):基于三种SVM(linearSVR.polySVR.RBFSVR)对Boston(波士顿房价)数据集(506,13+1)进行价格回归预测并对比各自性能 目录 输出结果 设计思路 ...

  9. ML之LiRSGDR:基于二种算法(LiR、SGDR)对Boston(波士顿房价)数据集(506,13+1)进行价格回归预测并对比各自性能

    ML之LiR&SGDR:基于二种算法(LiR.SGDR)对Boston(波士顿房价)数据集(506,13+1)进行价格回归预测并对比各自性能 目录 输出结果 设计思路 核心代码 输出结果 Bo ...

  10. EL之DTRFGBT:基于三种算法(DT、RF、GBT)对泰坦尼克号乘客数据集进行二分类(是否获救)预测并对比各自性能

    EL之DT&RF&GBT:基于三种算法(DT.RF.GBT)对泰坦尼克号乘客数据集进行二分类(是否获救)预测并对比各自性能 目录 输出结果 ​设计思路 核心代码 输出结果 设计思路 核 ...

最新文章

  1. 斯坦福大学深度学习与自然语言处理第三讲:高级的词向量表示
  2. 一、flask的基本使用-flask
  3. IDA Pro ARM指令集和Thumb指令集的切换
  4. 我们工作到底为了什么(这篇文章很重要)----强烈推荐
  5. UART_SEND详细设计方案
  6. tcp通讯一次最多能发送多少数据?_关于TCP/IP,必须知道的十个知识点
  7. c#位数不够0补充完_Java与C#比较,哪个语言更是适合你?
  8. php页面审核,深入理解用PHP实现页面注册审核
  9. 论文编辑——插入公式编号并对齐、插入图表编号、正文引用各类编号
  10. 2023年陕西师范大学宗教学考研上岸前辈备考经验指导
  11. 知识图谱从0到-1的笔记——6.知识推理
  12. ps如何制作霓虹字体
  13. 系统性谈谈软件可靠性——第3讲:软件可靠性设计方法
  14. jee6 学习笔记 5 - Struggling with JSF2 binding GET params
  15. 大陆引进《火影忍者》角色中文译名雷人出炉
  16. js实现页面表格内容的复制粘贴填充,实现快速填写
  17. canvas 将两张图片叠加
  18. 45台计算机的网络拓扑图,网络复习习题
  19. url资源(html相关)
  20. 上海青浦区大众驾校(科目二·自动挡)真实考场操作全程

热门文章

  1. git学习笔记-(11-git存储)
  2. 怎么解Linux内核温控,Linux Thermal 框架解析
  3. mysql 一台电脑多个服务_怎么在一台windows主机上安装多个mysql服务
  4. android runnable传递参数,Android – 如何将数据传递到RunOnUiThread中的Runnable?
  5. java exception 级别_Java异常体系概述
  6. 事务方法调用事务方法_实现系统调用的几种方法
  7. linux系统怎么拨号上网,如何用 Linux 拨号上网
  8. oracle永久表设置,Oracle 表空间简单管理永久表空间
  9. cookie被淘汰_可爱可恨的 Cookie
  10. SpringBoot系列(7):SpringBoot启动流程源码分析()