从 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
即可发出正确的信号。但是,我不知道如何更新已经存在的项目。例如。如果我只想更改对象的 latitude
或 longitude
。
QAbstractListModel 为您提供了一个辅助函数 index()
,它根据行号创建一个 QModelIndex。所以你应该可以使用这个信号:
int rowThatChanged = <whatever>
emit dataChanged(index(rowThatChanged), index(rowThatChanged));
我有一个简单的 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
即可发出正确的信号。但是,我不知道如何更新已经存在的项目。例如。如果我只想更改对象的 latitude
或 longitude
。
QAbstractListModel 为您提供了一个辅助函数 index()
,它根据行号创建一个 QModelIndex。所以你应该可以使用这个信号:
int rowThatChanged = <whatever>
emit dataChanged(index(rowThatChanged), index(rowThatChanged));