背景:业务中有很多Table表,每个表的内容也不相同,如果针对每个表自定义一个Model的话不太现实,现将Model抽象成通用的,用了两种方法实现。
一、用QList<QVariantList>做数据源
datamodel.h
#ifndef DATAMODEL_H
#define DATAMODEL_H
#include <QObject>
#include <QAbstractItemModel>
class DataModel : public QAbstractTableModel
{
Q_OBJECT
Q_PROPERTY(QStringList roles READ roles WRITE setRoles)
public:
DataModel(QObject *parent = 0);
~DataModel();
//继承基类的函数
QVariant data(const QModelIndex &index, int role) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QHash<int, QByteArray> roleNames() const; //重新实现roleNames()
QStringList roles() const;
void setRoles(const QStringList roles);
signals:
void dataChanged();
private:
QList<QVariantList> m_data;
QStringList m_roleList;
};
#endif // DATAMODEL_H
datamodel.cpp
#include "datamodel.h"
#include <QAbstractTableModel>
DataModel::DataModel(QObject *parent):
QAbstractTableModel(parent)
{
QVariantList list1;
list1.push_back("ceshi1");
list1.push_back("nan");
QVariantList list2;
list2.push_back("ceshi2");
list2.push_back("nv");
m_data.push_back(list1);
m_data.push_back(list2);
}
DataModel::~DataModel()
{
}
int DataModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return m_data.size();
}
int DataModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
if(m_data.isEmpty())
return 0;
return m_data.at(0).size();
}
QVariant DataModel::data(const QModelIndex &index, int role) const
{
if (role == Qt::DisplayRole) {
return m_data[index.row()].at(index.column());
}
else
{
int columnIdx = role - Qt::UserRole - 1;
QModelIndex modelIndex = this->index(index.row(), columnIdx);
return m_data[modelIndex.row()].at(modelIndex.column());
}
return QVariant();
}
QStringList DataModel::roles() const
{
return m_roleList;
}
void DataModel::setRoles(const QStringList roles)
{
if(!roles.isEmpty())
{
m_roleList = roles;
}
}
QHash<int, QByteArray> DataModel::roleNames() const
{
QHash<int, QByteArray> roles;
for(int i = 0;i < m_roleList.size();i++)
{
roles[Qt::UserRole+i+1] = m_roleList.at(i).toLocal8Bit();
}
return roles;
}
二、用QList<QMap<QString,QVariant>>做数据源
datamodel.h
#ifndef DATAMODEL_H
#define DATAMODEL_H
#include <QObject>
#include <QAbstractItemModel>
class DataModel : public QAbstractTableModel
{
Q_OBJECT
Q_PROPERTY(QStringList roles READ roles WRITE setRoles)
public:
DataModel(QObject *parent = 0);
~DataModel();
//继承基类的函数
QVariant data(const QModelIndex &index, int role) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QHash<int, QByteArray> roleNames() const; //重新实现roleNames()
QStringList roles() const;
void setRoles(const QStringList roles);
signals:
void dataChanged();
private:
QString getKey(int index) const;
private:
QList<QMap<QString,QVariant>> m_map;
QStringList m_roleList;
};
#endif // DATAMODEL_H
datamodel.cpp
#include "datamodel.h"
#include <QAbstractTableModel>
DataModel::DataModel(QObject *parent):
QAbstractTableModel(parent)
{
QMap<QString,QVariant> map_1;
map_1.insert("gender","nan");
map_1.insert("name","ceshi1");
QMap<QString,QVariant> map_2;
map_2.insert("name","ceshi2");
map_2.insert("gender","nv");
m_map.push_back(map_1);
m_map.push_back(map_2);
}
DataModel::~DataModel()
{
}
int DataModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
return m_map.size();
}
int DataModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
if(m_map.isEmpty())
return 0;
return m_map.at(0).size();
}
QVariant DataModel::data(const QModelIndex &index, int role) const
{
QString key = getKey(role);
return m_map[index.row()].value(key,"####");
}
QStringList DataModel::roles() const
{
return m_roleList;
}
void DataModel::setRoles(const QStringList roles)
{
if(!roles.isEmpty())
{
m_roleList = roles;
}
}
QHash<int, QByteArray> DataModel::roleNames() const
{
QHash<int, QByteArray> roles;
for(int i = 0;i < m_roleList.size();i++)
{
roles[Qt::UserRole+i+1] = m_roleList.at(i).toLocal8Bit();
}
return roles;
}
QString DataModel::getKey(int role) const
{
int columnIndex = role - Qt::UserRole - 1;
return m_roleList.at(columnIndex);
}
main.cpp
qmlRegisterType<DataModel>("DataModel", 1, 0, "DataModel");
main.qml
import QtQuick 2.0
import QtQuick.Controls 1.4
import DataModel 1.0
Item {
DataModel {
id:dataModel
roles: ["name","gender"]
}
TableView {
anchors.right: parent.right
model: dataModel
sortIndicatorVisible:true
width: 200
height: 300
TableViewColumn { role: "name"; title: "Title"; width: 100}
TableViewColumn { role: "gender"; title: "Gender";width: 100}
}
}
运行效果
运行效果是一样的,第一种方法和第二种方法的区别在于第一种方法在填装数据的时候必须顺序插入,在获取数据的时候也必须根据行列号获取,第二种方法只需约定好key值,也就是roles,这样填装的时候无需关心顺序