背景
Qt 模型视图编程中模型定义了标准接口对数据进行访问,可根据需求继承对应的抽象模型类来实现自定义的数据模型。一个基本的数据模型至少要实现以下虚函数:
①.rowCount:行数,返回要显示多少行;
②.columnCount:列数,返回要显示多少列
③.data:读取数据,返回每个单元格要显示的内容
可编辑数据模型
①.概念
视图通过标准接口获取数据并定义显示方式;视图不会主动更新数据的显示,模型使用信号与槽机制通知视图数据变化。
②.关键虚函数
flags:返回该数据项是否可被编辑的标记
setData:模型对外提供的可进行数据修改的接口
③.数据变化信号
dataChanged:信号参数为数据变化的起始和结束范围,使用信号通知视图数据变化。
④.数据项角色
在数据读取接口 data 中,使用 Qt::EditRole 来设置数据编辑时的默认值。
在视图中修改数据
①.TableModelDemo.h 文件
#include <QAbstractTableModel>
struct student
{
QString name;
int age;
QString sex;
};//测试用数据结构
Q_DECLARE_METATYPE(student)
class TableModelDemo : public QAbstractTableModel
{
Q_OBJECT
public:
TableModelDemo(QList<student> & list, QObject *parent = nullptr):QAbstractTableModel(parent),m_list(list){};
~TableModelDemo() {};
protected:
virtual int rowCount(const QModelIndex &parent) const override;//
virtual int columnCount(const QModelIndex &parent) const override;//
virtual QVariant data(const QModelIndex &index,int role) const override;//
virtual Qt::ItemFlags flags(const QModelIndex &index)const override;//
virtual bool setData(const QModelIndex &index,const QVariant & value, int role = Qt::EditRole) override;//
private:
QList<student> &m_list;//对内存中数据的引用
};
②.TableModelDemo.cpp 文件
int TableModelDemo::rowCount(const QModelIndex &parent) const
{
return m_list.size();
}
int TableModelDemo::columnCount(const QModelIndex &parent) const
{
return 3;
}
QVariant TableModelDemo::data(const QModelIndex &index, int role) const
{
switch (role)
{
case Qt::DisplayRole:
case Qt::EditRole://数据编辑时的默认值
{
int r = index.row();
int c = index.column();
switch (c)
{
case 0:
return m_list[r].name;
break;
case 1:
return m_list[r].age;
break;
case 2:
return m_list[r].sex;
break;
default:
break;
}
}
break;
default:
return QVariant();
break;
}
}
Qt::ItemFlags TableModelDemo::flags(const QModelIndex &index) const
{
return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
}
bool TableModelDemo::setData(const QModelIndex & index, const QVariant & value, int role)
{
switch (role)
{
case Qt::EditRole:
{
int r = index.row();
int c = index.column();
switch (c)
{
case 0:
m_list[r].name = value.toString();
break;
case 1:
m_list[r].age = value.toInt();
break;
case 2:
m_list[r].sex = value.toString();
break;
default:
break;
}
}
emit dataChanged(index, index);
return true;
default:
break;
}
return true;
}
③.使用自定义模型
QList<student> m_list;//全局数据
student s;
s.age = 18;
s.name = "张三";
s.sex = "男";
m_list.append(s);
s.age = 16;
s.name = "李四";
s.sex = "女";
m_list.append(s);
auto mode = new TableModelDemo(m_list);
ui.tableView->setModel(mode);
ui.tableView_2->setModel(mode);
如上图所示,当在视图1 中编辑数据后,在视图2 中自动同步更新显示编辑结果。
在内存中修改数据
①.概念
在应用程序中可以直接在界面进行数据的编辑来修改内存中数据;也会有在另外的过程直接修改内存数据,然后通知界面进行显示。
②.视图数据更新
视图不会主动更新数据的显示,必须通过信号通知视图数据发生变化。
③.代码示例
在按钮单击事件中模拟修改内存数据
connect(ui.pushButton, &QPushButton::clicked, [mode]() {
m_list[0].age = 28;
auto index = mode->index(0, 1, QModelIndex());
emit mode->dataChanged(index, index);//通知视图显示
});