I'm displaying data in a GridView
from a custom QAbstractListItem
subclass (implementation here ). Adding and removing items works fine, QML is notified of the changes and transitions work fine.
Now I'm trying to set a property of an Item inside the model and have QML react on it. The problem is, the onPropertyChanged
inside QML is not called.
Here is the property in C++:
// item.h
Q_PROPERTY(bool pToBeDeleted READ toBeDeleted NOTIFY toBeDeletedChanged)
// item.cpp
void Item::requestDelete()
{
toBeDeleted_m = true;
qDebug() << "emitting";
emit toBeDeletedChanged();
}
This is what the GridView looks like:
// main.qml
GridView {
id: grid
// ...
model: empty
delegate: customComponent {
toBeDeleted: pToBeDeleted
}
ListModel {
id: empty
}
}
When the program starts, grid
's model
is set to my itemmodel.
And this is the QML type that does not see the changes:
// customComponentForm.ui.qml
Item {
property bool toBeDeleted: false
}
// customComponent.qml
CustomComponentForm {
onToBeDeletedChanged: {
console.debug("change")
}
}
Now when I call the method from inside the model like this:
this->items.at(i++)->requestDelete();
The output shows emitting
but not change
.
I have tried to include
emit dataChanged(createIndex(i, 0), createIndex(i, 0));
which did result in onToBeDeletedChanged
to be called sometimes , but that also resulted in some wonky behaviour with the error
DelegateModel::item: index out range 3 3
Two things went wrong here. First, because of the ++ at
this->items.at(i++)->requestDelete();
the dataChanged
emit had the wrong index which resulted in wrong items being updated. Second of all,
emit dataChanged(createIndex(i, 0), createIndex(i, 0));
was missing the third argument, and since in another attempt I had tried inline defining of a Vector the wrong way, I didn't find this to be the problem right away. The right call here would have been
QVector<int> v;
v.append(Qt::UserRole + 7 + 1);
// pToBeDeleted being the 7th property, always check this with
// roleNames()[Qt::UserRole + i + 1]. It should say your property.
emit dataChanged(createIndex(i, 0), createIndex(i, 0), v);
My mistake.
But on another note, since the rolename index seems to be platform dependent and signaling the change from the model is somewhat of a dirty approach, a better solution (as suggested by Kevin Krammer ) would be to rewrite the itemmodel to only contain a single property, which is the QObject
item. That way QML is notified of the changes item's properties have.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.