很多开发中都用到了表格,如何使用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