QML ListView does not reflect updates from its C++ data model [Solved]
-
My model inherits QAbstractListModel, I have a method to clear all items in the list, which is triggered by a mouse press event from the QML file, I'm able to receive this event fine. While the C++ model does get cleared, the ListView does not seem to reflect that change on the UI.
Relevant snippet from the header file of my model.
my_data_model.h
@class MyDataModel : public QAbstractListModel
{
public:
MyDataModel();
int rowCount( const QModelIndex& ) const;
QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
void clearMyData();
private:
QList< MyData > my_data;
};@my_data_model.cpp
@void MyDataModel::clearMyData()
{
my_data.clear();
}@The qml file's relevant code snippet. name and content are properties derived through the data model's template structure.
my_data.qml
@Rectangle {
id:listRectangle
width: 650; height: 250ListView { id:listView objectName: "listView" width: parent.width; height: parent.height anchors.centerIn: parent clip:true spacing: 5 model: myDataModel focus: false delegate: Rectangle { id: delegate objectName: name Text { id: titleText text: content } MouseArea { id:ma anchors.fill: parent onClicked: { listView.currentIndex = index; } } } }
}@
The qml is invoked like this:
model_usage_widget.cpp
@xView = new QDeclarativeView(this);
context = xView->engine()->rootContext();
MyDataModel myDataModel;
context->setContextProperty("myDataModel", &myDataModel);
xView->setSource(QUrl("qrc:/ui/qml/my_data_model.qml"));
xLayout = new QHBoxLayout(this);
xLayout->setMargin(0);
xLayout->addWidget(xView);
this->setLayout(xLayout);
this->show();@this is an object that inherits QWidget
I've included all relevant code above. I created my list with one item, and tried to clear it but the QML does not seem to update it's view. Do I have to add anything else?
-
Hi,
my_data.clear() will just clear the list but you will the view to be notified about the changes. This can be done by wrapping it up in "beginResetModel":http://doc.qt.io/qt-5/qabstractitemmodel.html#beginResetModel and endResetModel:
@
beginResetModel();
my_data.clear();
endResetModel();
@ -
This code works for me:
@ emit layoutAboutToBeChanged();
my_data.clear();
emit layoutChanged();@ -
So, with this the Application no longer crashes but my view still seems to hold the model item's in it's view but the I'm not able to scroll between the items.
[quote author="ondrejandrej" date="1421854871"]This code works for me:
@ emit layoutAboutToBeChanged();
my_data.clear();
emit layoutChanged();@[/quote]As an aside, it'd be nice to find a complete example of a c++ model and a qml view where items are added and removed dynamically but I'm not able to find one online. I'd really appreciate if someone could link it for me.
-
You are creating a model, but it goes out of scope immediately after constructor terminates (I suppose your last code snippet is in a constructor).
You should ensure that the model remains in existence while the QML view is showing, e. g. by allocating on heap:
@MyDataModel *myDataModel = new MyDataModel(this);
context->setContextProperty("myDataModel", myDataModel);@ -
You are using "it's" wrongly. Have a look at http://www.elearnenglishlanguage.com/blog/english-mistakes/its/ . You have it also in the title.
-
bq. I just tried inserting that, and my Application Crashed as soon as that code was invoked. Narrowed it down to endResetModel() being the culprit.
I have been using this approach in all my projects where ListView is used. It worked all the time.
Why are you using QDeclarativeView ? Aren't you using Qt 5 ? -
[quote author="kwisatz" date="1421877712"]:D Thanks for pointing that out!
[/quote]
It's good that you fixed it :D -
Sorry, should have made this clear earlier on, I'm using Qt 4.8.4.
[quote author="p3c0" date="1421902494"]bq. I just tried inserting that, and my Application Crashed as soon as that code was invoked. Narrowed it down to endResetModel() being the culprit.
I have been using this approach in all my projects where ListView is used. It worked all the time.
Why are you using QDeclarativeView ? Aren't you using Qt 5 ?[/quote] -
Well then I'm not sure why it crashes. Qt 4.8.4 still is quite old in Qt4 series. Can you try it on Qt 4.8.6 ?
-
Okay, I did manage to get this to work finally.
When clearing data, I used:
@ beginResetModel();
m_data.clear();
endResetModel();@When removing an individual item in the data, I used:
@ beginRemoveRows(QModelIndex(), index, index);
m_data.removeAt(index);
endRemoveRows();@And I worked on this bit of code separately from my main application. Will have to see what kind of fun awaits when I merge the changes with the rest of the application ;)
Appreciate the help folks!