码迷,mamicode.com
首页 > 其他好文 > 详细

Qt表格之Model/View实现

时间:2014-10-29 00:31:53      阅读:328      评论:0      收藏:0      [点我收藏+]

标签:qt   模型视图   

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

bubuko.com,布布扣

Qt表格之Model/View实现

标签:qt   模型视图   

原文地址:http://blog.csdn.net/soso101/article/details/40556179

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!