Gridview dynamic update on C++ model setData() or qml ListModel set()
-
wrote on 21 Mar 2020, 20:48 last edited by
Hi all,
I'm having problems understanding why this is not working, I just want to have an item in the view dynamically updated when I change the data in the model using the ListModel method set() , I've also used a C++ model and setData() which emits dataChanged() signal but I can't see any refresh though. I'm stucked.
import QtQuick 2.5 import QtQuick.Controls 2.2 import QtQuick.Layouts 1.2 Dialog { id: mydialog anchors.centerIn: parent width: parent.width / 2 height: parent.height / 2 padding: 32 modal: true ListModel { id: theModel ListElement { number: 0 } ListElement { number: 1 } ListElement { number: 2 } ListElement { number: 3 } ListElement { number: 4 } ListElement { number: 5 } ListElement { number: 6 } ListElement { number: 7 } ListElement { number: 8 } ListElement { number: 9 } } ColumnLayout { anchors.fill: parent property int count: 9 Button { Layout.alignment: Qt.AlignTop Layout.preferredHeight: 20 Layout.preferredWidth : 50 text: qsTr("add") onClicked: { console.debug("add element") theModel.append({"number": ++parent.count}); } } Button { Layout.alignment: Qt.AlignCenter Layout.preferredHeight: 20 Layout.preferredWidth : 50 text: qsTr("set") onClicked: { console.debug("set") theModel.set(0, {"number": 12}); } } GridView { Layout.alignment: Qt.AlignBottom id: view Layout.preferredHeight: 100 Layout.preferredWidth : 400 //anchors.margins: 20 clip: true model: theModel cellWidth: 45 cellHeight: 45 delegate: numberDelegate } Component { id: numberDelegate Label { width: 400 height: 40 text: index } } } }
follows a second attempt which is more my real case ( I have a custom C++ model ) registered in My.Models 1.0 -> MyModel . It's bit better as I'm able to change the values in the view but the view items are not refreshed until I scroll up or down. Using grid.forceLayout() didn't solve, the only solution I've found is to set grid.model = 0 and reset the model with grid.model = mymodel . I expect this to work without any special trick. here is the code ( I've stripped it lot of lines so maybe the syntax is not correct, hope it's enough ):
import QtQuick 2.12 import QtQuick.Controls 2.5 import QtQuick.Layouts 1.3 import QtQuick.Controls.Material 2.3 import My.Models 1.0 Dialog { id: root anchors.centerIn: parent width: 1000 height: 700 padding: 32 modal: true Connections { target: MyClass // MyClass emit this signal onFinishedParsing: { // this is an example trying to set all model data to "0.2" , in a real case this data come from MyClass for (var i = 0; i < mymodel.rowCount(); i++) { mymodel.setData(mymodel.index(i, 0),"0.2",MyModelModel.Value) } } ColumnLayout { anchors.fill: parent spacing: 16 GridView { id: grid Layout.fillHeight: true Layout.fillWidth: true contentWidth: width cellWidth: width / 4 cellHeight: 80 clip: true model: MyModel { id: mymodel } delegate: Label { text: model.value } } }
the setData method in MyModel is:
bool SimplsModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.isValid() && role == SimplsModel::Roles::Value) { m_rowData[index.row()].value = value.toFloat(); emit dataChanged(index, index, {SimplsModel::Roles::Value}); return true; } return false; }
I'm really stucked , can't see what's wrong. any help would be really appreciated. thanks.
-
wrote on 22 Mar 2020, 09:40 last edited by
Here is my code which use the
QAbstractListModel
: TestModelWhen change the data, try call
beginResetModel
andendResetModel
.void TestModel::addDao(const QString &name, int age) { beginResetModel(); m_datas.append(Dao(name, age)); endResetModel(); }
-
wrote on 23 Mar 2020, 05:39 last edited by
When change the data, try call beginResetModel and endResetModel.
Don't (I wouldn't anyhow) do that, that's a big hammer. I do use that but only for a whole set of data.
For an simple append ~not really right.setData & emit dataChanged is correct.
When reimplementing the setData() function, this signal must be emitted explicitly.
I emit that the whole row changed with mine (see the first 2 args below), but I'm not sure even this is fully optimal. It does work for me - just working is enough for me atm and I'd like to get time to experiment restricting to a unique.
emit QAbstractTableModel::dataChanged(QAbstractTableModel::index(intOfIter, 0), QAbstractTableModel::index(intOfIter, columnCount()-1), QVector<int>() << role);
I'm still getting my head around trying to get setData actually working from QML side with custom roles, from Table view but this works from Cpp backend, I'm trying to get a complex control sorted that can handle updates with dynamic delegates from QML.
Hopefully this is just enough to get you across the line and moving again too.
-
Here is my code which use the
QAbstractListModel
: TestModelWhen change the data, try call
beginResetModel
andendResetModel
.void TestModel::addDao(const QString &name, int age) { beginResetModel(); m_datas.append(Dao(name, age)); endResetModel(); }
wrote on 23 Mar 2020, 11:27 last edited bybeginResetModel() / endResetModel()
works but actually is a lot of overhead in in setData, I think it's ok if I want to upadate the whole model data in one shot , thanks
I've tried this but it didn't solve, as before it do set the data but the view doesn't refresh de delagates, maybe I didn't realize how to apply it for a QAbstractListModel:
emit QAbstractListModel::dataChanged(QAbstractListModel::index(index.row()), QAbstractListModel::index(index.row()), QVector<int>() << SimplsModel::Roles::Value); or emit QAbstractListModel::dataChanged(QAbstractListModel::index(index.row()), QAbstractListModel::index(index.row()), QVector<int>() << Qt::DisplayRole);
Strange that we have to fight to make this work, I can't find code examples about people achieving this, Am I doing something unusual ? ( I wander )
thanks
-
wrote on 7 Dec 2020, 11:05 last edited by
Try calling a signal without the last parameter.
emit dataChanged(index, index);
-
wrote on 7 Dec 2020, 13:22 last edited by
If I understood correctly, it wasn't even working for a QML
ListModel
. I think that would need to be resolved first before getting bogged down with the C++ model.