很多开发中都用到了表格,如何使用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 ); // 标志,比如是否可选或可编辑,如果需要编辑必须返回可编辑flag virtual 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,显示成一个CheckBox if( 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 */ ) { // 设置什么条件下可以编辑,假设只设置checkstate if(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 ""; else return 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); } }
原文地址:http://blog.csdn.net/soso101/article/details/40556179