需要实现的函数
class ItemModel : public QAbstractTableModel
{
Q_OBJECT
public:
ItemModel(QObject* parent = Q_NULLPTR);
~ItemModel();
// 返回行的数量
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override;
//返回列的数量
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override;
//返回数据
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
//返回单元格的标志,就是通过此函数来实现CheckBox和SpinBox
virtual Qt::ItemFlags flags(const QModelIndex& index) const override;
//数据变化后设置数据
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::DisplayRole) override;
//返回表头数据
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
//自定义的数据插入函数
void setData(ItemData data);
private:
QList<ItemData> m_datas;
QStringList m_header;
};
其中ItemData结构体的定义如下
class ItemData {
public:
int Id;
int Count;
bool IsEnable;
};
实现
#include "ItemModel.h"
ItemModel::ItemModel(QObject* parent)
: QAbstractTableModel(parent)
{
m_header << "Id" << "Name" << "state";
}
ItemModel::~ItemModel()
{
}
int ItemModel::rowCount(const QModelIndex& parent) const
{
return m_datas.count();
}
int ItemModel::columnCount(const QModelIndex& parent) const
{
return 3;
}
QVariant ItemModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
return QVariant();
int nRow = index.row();
int nColumn = index.column();
ItemData data = m_datas.at(nRow);
switch (role)
{
case Qt::DisplayRole:
{
if (nColumn == 0)
return data.Id;
//在显示角色下也要加上这一行,否则不会显示count的数值,因为只有在编辑时会触发 Qt::EditRole: 才能获取到data.Count
if (nColumn == 1)
return data.Count;
return "";
}
case Qt::EditRole:
{
//在编辑状态下获取Count字段的值显示到界面上
if (nColumn == 1)
return data.Count;
return "";
}
case Qt::CheckStateRole:
{
//返回CheckBox的状态
if (nColumn == 2)
return data.IsEnable ? Qt::Checked : Qt::Unchecked;
}
default:
return QVariant();
}
return QVariant();
}
Qt::ItemFlags ItemModel::flags(const QModelIndex& index) const
{
if (!index.isValid())
return QAbstractItemModel::flags(index);
//设置通用单元格的标志,即可选的状态
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
//对于SpinBox我们让他可编辑
if (index.column() == 1)
flags |= Qt::ItemIsEditable;
//对于CheckBoxs额外添加此状态
if (index.column() == 2)
flags |= Qt::ItemIsUserCheckable;
return flags;
}
QVariant ItemModel::headerData(int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/) const
{
if (role == Qt::DisplayRole) {
if (orientation == Qt::Horizontal) {
return m_header.at(section);
}
}
return QAbstractTableModel::headerData(section, orientation, role);
}
void ItemModel::setData(ItemData data)
{
m_datas.append(data);
//更新模型
beginResetModel();
endResetModel();
}
//当界面上的值变化后会调用此函数来进行处理,所以我们在此处更新我们的数据 m_datas
bool ItemModel::setData(const QModelIndex& index, const QVariant& value, int role /*= Qt::DisplayRole*/)
{
if (!index.isValid())
return false;
int nColumn = index.column();
ItemData data = m_datas.at(index.row());
switch (role)
{
case Qt::DisplayRole:
{
if (nColumn == 0)
{
data.Id = value.toInt();
m_datas.replace(index.row(), data);
emit dataChanged(index, index);
return true;
}
}
case Qt::EditRole:
{
if (nColumn == 1) {
data.Count = value.toInt();
m_datas.replace(index.row(), data);
emit dataChanged(index, index);
return true;
}
}
case Qt::CheckStateRole:
{
if (nColumn == 2)
{
data.IsEnable = (value.toInt() == Qt::Checked);
m_datas.replace(index.row(), data);
emit dataChanged(index, index);
return true;
}
}
default:
return false;
}
return false;
}
使用
ui.tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
ui.tableView->setModel(&m_item_model);
for (size_t i = 0; i < 10; i++)
{
ItemData data;
data.Id = i;
data.Count = i * 2;
data.IsEnable = true;
m_item_model.setData(data);
}
后记
- 由于是Demo ,所以上述代码的格式上可能比较随意
- 在使用的过程中,发现同时使用QAbstractTableModel 和 QStyledItemDelegate时,只会触发QStyledItemDelegate的paint调用,还不知道具体的原因,有知道的大佬欢迎评论区留言
- 针对第二点可以在paint函数中自己去绘制控件