当多个 View 展示同一个数据集中的部分数据项时,其中一个 View 进行了增删改操作,也需要同步到其他的 View。有两种比较简单的解决方案:
方案一:如果都是同一种 View(如都是 ListView),那可以共用一个 Model 实例,通过 Proxy 来辅助完成过滤和选择等操作,实践起来也比较简单,几乎不用自己做额外的同步。
方案二:如果数据项需要同时在 ListView、TreeView 等不同的场景使用,那单个 Model 实例的方式实现起来就很麻烦了,这时可以让多个 Model 持有同一组数据项指针(建议用智能指针),更新之后通知所有关联的 View 进行同步刷新。
本文 Demo 采用方案二共享数据项指针的方式,UI 使用 QML 实现。通过 Model 的 data 接口访问数据时,是可以返回指针的,然后 Delegate 通过指针访问数据项的属性。但是 QML 中没法识别智能指针(至少 Qt5 下测试识别不了),只能从智能指针取出原始指针后返回给 QML。但是 QML Delegate 访问原始指针的属性还有问题,就是初始化或者增删时,可能报属性未定义或者是不存在,所以还是先老老实实从 data 接口返回数据项的属性值,而不是返回指针,这样排查问题也容易。
除了数据项指针,还需要一个对象(DataSource)来关联各个 Model/View,这样在一个 Model/View 中的增删改操作,就能同步到其他 Model/View 中。修改时调用 DataSource 接口修改,同时触发更新信号,关联 Model 收到信号后进行同步。考虑到一般编辑接口是需要 Model 的行列号来定位当前项的,QML 中可以通过 Model 来间接调用 DataSource 的增删改,而不是直接操作 DataSource 的增删改。
DataSource 接口定义如下:
#pragma once
#include
#include
struct DataInfo
{
QString key;
int value = 0;
};
class DataSource : public QObject
{
Q_OBJECT
private:
explicit DataSource(QObject *parent = nullptr);
public:
~DataSource();
static DataSource* getInstance();
//增删改接口
void deleteItem(QSharedPointer item);
void appendItem(const QString &key, int value);
void appendItem(QSharedPointer item);
void updateItem(QSharedPointer item);
//根据value范围查询数据
QList searchItemByValue(int min, int max);
signals:
//增删改通知其他view更新
void itemDeleteNotify(QSharedPointer item);
void itemAppendNotify(QSharedPointer item);
void itemUpdateNotify(QSharedPointer item);
private:
//存储着所有的数据
QList dataList;
};
View 中操作 Model 的增删改接口:
Button {
text: "update"
onClicked: {
//update更新所有view中的该item
data_model.updateItemByRow(model.index, "key", 123)
}
}
Button {
text: "delete"
onClicked: {
//删除item
data_model.deleteItemByRow(model.index)
}
}
void DataModel::deleteItemByRow(int row)
{
if(row < 0 || row >= dataList.size())
return;
DataSource::getInstance()->deleteItem(dataList.at(row));
}
void DataModel::updateItemByRow(int row, const QString &key, int value)
{
if(row < 0 || row >= dataList.size())
return;
auto item = dataList.at(row);
item->key = key;
item->value = value;
DataSource::getInstance()->updateItem(item);
}
DataSource 信号通知关联 Model 刷新:
DataModel::DataModel(QObject *parent)
: QAbstractListModel(parent)
{
auto source = DataSource::getInstance();
connect(source, &DataSource::itemAppendNotify,
this, [this](QSharedPointer item){
//符合条件,插入
if(item->value >= searchMin && item->value = 0){
beginRemoveRows(QModelIndex(), row, row);
dataList.removeAt(row);
endRemoveRows();
}
});
connect(source, &DataSource::itemUpdateNotify,
this, [this](QSharedPointer item){
int row = dataList.indexOf(item);
if(row >= 0){
//已存在,判断是否需要移除
if(item->value >= searchMin && item->value value >= searchMin && item->value
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?