Qt表格之Model/View实现

来源:互联网 发布:电信移动网络自由切换 编辑:程序博客网 时间:2024/05/21 09:26

很多开发中都用到了表格,如何使用Qt做表格?比较简单的,我们可以使用QTableWidget,但是它有个问题,就是数据量不能太大,一旦数据量比较大的话就会带来内存问题。Qt还给我们提供了一样利器--Model/View。模型视图,接触Qt的都不会陌生,对新手来说可能不太好理解,没关系,Qt提供了强大的Assist文档和更加直观的Demo,相信看过之后使用来说就没有问题了。本篇文章来列出一个简单的例子,使用的就是表格的模型视图,在代码中给出了简单的注释说明。为什么要采用这种方式?试过的人都可以看到它的显示效率是比QTableWidget要高出许多的。其实,测试发现,它的行数有个上线,也就是说把全部数据载入内存中,数据时几千万行。不过,这个限制不是问题,因为你不可能一眼看几千万行的数据,合理的设计可以“显示”过亿条数据,当然,注意我说的“合理的设计”,以后有时间再具体写下代码。

#ifndef MYTABLEMODEL_H#define MYTABLEMODEL_H#include <QAbstractTableModel>#include <QSortFilterProxyModel>#include <QVector>#include <QStringList>/************************************************************************//* 模型数据类                                                                     *//************************************************************************/class MyModelItem{public:MyModelItem(){m_id = 0;m_name = "";m_value = 0;m_selected = false;}void createExampleItem();public:int m_id;QString m_name;int m_value;bool m_selected;};/************************************************************************//* 表格模型                                                                     *//************************************************************************/class MyTableModel : public QAbstractTableModel{public:MyTableModel(QObject *parent = NULL);~MyTableModel();// 表格的行数,不要遗漏const哦virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;// 表格的列数,不要遗漏const哦virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;// 表格数据,返回每个单元格的各种role的值virtual QVariant data(const QModelIndex &index, int role  = Qt::DisplayRole ) const;// 编辑时实现,非必须,有修改值的需求时实现即可virtual bool setData ( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole );// 标志,比如是否可选或可编辑,如果需要编辑必须返回可编辑flagvirtual Qt::ItemFlags flags(const QModelIndex & index) const;// 可以返回行列名称virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;// 返回模型指针,仅仅为了例子使用方便QVector<MyModelItem*>* dataModel() { return &m_dataModel; }private:/*! 数据模型 */QVector<MyModelItem*> m_dataModel;/*! 列名称list */QStringList m_columnList;};#endif // MYTABLEMODEL_H
#include "MyTableModel.h"#include <QIcon>static const int col_id = 0;static const int col_name = 1;static const int col_value = 2;static const int col_state = 3;MyTableModel::MyTableModel(QObject *parent): QAbstractTableModel(parent){m_columnList << "ID" << "Name" << "Value" << "State";}MyTableModel::~MyTableModel(){qDeleteAll(m_dataModel);}int MyTableModel::rowCount( const QModelIndex& parent ) const{return m_dataModel.size();}int MyTableModel::columnCount( const QModelIndex &parent ) const{return m_columnList.count();}QVariant MyTableModel::data( const QModelIndex &index, int role ) const{if(index.row() > m_dataModel.size())return QVariant();// 其他的role一定要有返回值,默认给QVariant()就行if((Qt::DisplayRole != role) && (Qt::EditRole != role) && (Qt::DecorationRole != role)&& (Qt::BackgroundColorRole != role) && (Qt::CheckStateRole != role)){return QVariant();}int curRow = index.row();QVariant  theResult;switch(index.column()){case col_id:{// CheckState,显示成一个CheckBoxif( Qt::CheckStateRole == role   ){theResult = m_dataModel[index.row() ]->m_selected ? Qt::Checked : Qt::Unchecked;}else if (role == Qt::DisplayRole || role == Qt::EditRole)//显示、编辑State{theResult = QString::number(m_dataModel[index.row()]->m_id);}break; }case col_name:{if (role == Qt::DisplayRole || role == Qt::EditRole){theResult = m_dataModel[index.row() ]->m_name;}break;}case col_value:{if (role == Qt::DisplayRole || role == Qt::EditRole){theResult = QString::number(m_dataModel[index.row() ]->m_value);}break;}case  col_state:{if (Qt::DecorationRole == role){theResult = QIcon(QPixmap(QString(":/TestModelView/Resources/%1.jpg").arg(rand() % 4)));}break;}}return theResult;}bool MyTableModel::setData( const QModelIndex & index, const QVariant & value, int role /*= Qt::EditRole */ ){// 设置什么条件下可以编辑,假设只设置checkstateif(Qt::CheckStateRole != role ||  index.column() != col_id )return false;if( index.row() >= m_dataModel.size())return false;m_dataModel[index.row() ]->m_selected =  (value.toInt() == Qt::Checked );return true;}Qt::ItemFlags MyTableModel::flags( const QModelIndex & index ) const{Qt::ItemFlags flag =  QAbstractTableModel::flags(index);// 假设第一列的checkstate可以编辑if (index.column()  == col_id){flag = flag | Qt::ItemIsUserCheckable;return flag;}return QAbstractTableModel::flags(index);}QVariant MyTableModel::headerData( int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/ ) const{if (role == Qt::DisplayRole){if (orientation == Qt::Horizontal) {if (section < 0 || section >= m_columnList.size())return "";elsereturn m_columnList[section];}else{return QVariant(section + 1);}}return QAbstractTableModel::headerData(section, orientation, role);}void MyModelItem::createExampleItem(){m_id = rand();m_name = QString("name%1").arg(m_id);m_value = rand() % 10000;m_selected = (m_value % 2 == 0);}
在应用程序中仅仅使用在主窗口ui中加入了QTableView,然后调用了setModel。

#include "TestModelView.h"TestModelView::TestModelView(QWidget *parent, Qt::WFlags flags): QMainWindow(parent, flags){ui.setupUi(this);createExampleData();ui.tableView->setModel(m_model);}TestModelView::~TestModelView(){}void TestModelView::createExampleData(){m_model = new MyTableModel(this);QVector<MyModelItem*>* dataModel = m_model->dataModel();for (int i = 0; i < 100; i++){MyModelItem* item = new MyModelItem;item->createExampleItem();dataModel->push_back(item);}}

1 0
原创粉丝点击