从 C++ 更新 QAbstractListModel 中的元素

Updating elements in a QAbstractListModel from C++

我有一个简单的 QML 应用程序。 此应用程序包含一个 class ObjectModel : public QAbstractListModel,其中包含一个 ParesisObjectList* mList,其中包含在 GUI 上显示的数据。

QML 片段:

ListView {
    width: parent.width
    height: parent.height

    model: ObjectModel {
        list: paresisObjectList
    }
    delegate: Text {
        text: type + ": " + identifier + " " + latitude
    }
}

应用程序通过 UDP 连接到服务器,服务器不断发送新的和更新的数据字段以显示在 GUI 上。 但是,有我的问题。我可以使用以下方法插入新对象,每当通过 UDP 收到新项目时调用该方法:

void ParesisObjectList::appendItem(ObjectModelItem item)
{  
    emit preItemAppended();
    mItems.append(item);
    emit postItemAppended();
}

但是,我不确定如何更新 mItems 中已经存在的项目。我的意思是,更改值没问题,但是,我必须以某种方式通知我的 GUI 以确保值也在 GUI 中更新。

我知道,我必须在 ObjectModel 中发出 dataChanged(...) 信号,但它需要更新元素位置的 QModelIndex。 但是,由于更新来自 C++ 端而不是通过 QML(在调用 bool ObjectModel::setData(const QModelIndex &index, const QVariant &value, int role) 时),我不知道如何获取 QModelIndex 来更新特定值。

因此,我的问题是:如何从 C++ 更新 ParesisObjectlist 中的元素?

编辑:

ParesisObjectList.h

struct ObjectModelItem
{
    QString type;
    double longitude;
    double latitude;
    int identifier;
};

class ParesisObjectList : public QObject
{
    Q_OBJECT
public:
    explicit ParesisObjectList(QObject *parent = nullptr);

    QVector<ObjectModelItem> items() const;

    bool setItemAt(int index, const ObjectModelItem& item);
    bool setItem(const ObjectModelItem& item);

signals:
    void preItemAppended();
    void postItemAppended();

    void preItemRemoved(int inex);
    void postItemRemoved();

    void objectUpdated(ObjectModelItem&, int position);

public slots:
    void appendItem(ObjectModelItem);
    void removeItem(int identifier);

private:
    QVector<ObjectModelItem> mItems;
};

ParesisObjectList.cpp:

ParesisObjectList::ParesisObjectList(QObject *parent) : QObject(parent)
{
}

QVector<ObjectModelItem> ParesisObjectList::items() const
{
    return mItems;
}

bool ParesisObjectList::setItemAt(int index, const ObjectModelItem &item)
{
    if(index < 0 || index >= mItems.size()) {
        return false;
    }
    const ObjectModelItem& oldItem = mItems.at(index);
    if(item.identifier == oldItem.identifier) {
        return false;
    } else {
        mItems[index] = item;
        return true;
    }
}

void ParesisObjectList::appendItem(ObjectModelItem item)
{  
    emit preItemAppended();
    mItems.append(item);
    emit postItemAppended();
}

void ParesisObjectList::removeItem(int identifier)
{
    for(int i = 0; i < mItems.size(); i++) {
        if(mItems.at(i).identifier == identifier) {
            emit preItemRemoved(i);
            mItems.removeAt(i);
            emit postItemRemoved();
        }
    }
}

要向我的 ParesisObjectList 添加项目,我只需调用 appendItem 即可发出正确的信号。但是,我不知道如何更新已经存在的项目。例如。如果我只想更改对象的 latitudelongitude

QAbstractListModel 为您提供了一个辅助函数 index(),它根据行号创建一个 QModelIndex。所以你应该可以使用这个信号:

int rowThatChanged = <whatever>
emit dataChanged(index(rowThatChanged), index(rowThatChanged));