Unsolved ListView issue when updated (current index set to 0)
-
Hi all,
I meet an issue with listView when the model is updated from C++.
After each update from C++, the current index is set to 0 and the view return to beginning of it !
In the C++ side, the model exposed is declared like this :Q_PROPERTY(QList<QObject*> debugList READ getDebugList NOTIFY debugListChanged)
in qml :
Component { id: nameDelegate Item { id: delegateItem height: ListView.isCurrentItem ? 25 : textDebug.height width:debugRx.width Behavior on height { NumberAnimation { duration: 750 easing.type: "InOutQuint" } } Text { id:textDebug text: model.modelData.data color: model.modelData.color width: debugRx.width //height: 20 lineHeight: 15 lineHeightMode: Text.FixedHeight scale: parent.height/height transformOrigin: Item.Left wrapMode: Text.WordWrap font{ family: "arial" pixelSize:16 } } } } ListView { id:listViewDebug snapMode: ListView.SnapOneItem property string name: "listeDebug" property bool scrollDebugAuto: true property int scrollDebugIndex: 0 bottomMargin: 5 anchors.fill: parent anchors.topMargin: 5 anchors.bottomMargin: 5 anchors.leftMargin: 2 anchors.rightMargin: 2 clip:true model:device.debugList focus:true delegate: nameDelegate ScrollBar.vertical: ScrollBar{ id:scrollBarDebug } highlight: Rectangle { width: listViewDebug.width; border.color: "gray" border.width: 2 color : "green" opacity: 0.3 radius:5 Behavior on y { SpringAnimation { spring: 3 damping: 0.2 } } } highlightFollowsCurrentItem: true //highlightRangeMode : ListView.StrictlyEnforceRange currentIndex: scrollDebugAuto ? listViewDebug.count-1 : scrollDebugIndex onCurrentIndexChanged:{ console.log("current index update :"+currentIndex) } onModelChanged: { console.log("current index :"+currentIndex); console.log("save index : "+scrollDebugIndex) } Component.onCompleted: positionViewAtIndex(count - 1, ListView.Beginning) } }
When the property scrollDebugAuto is true it work fine (the view stay et end of the listView) but when it false the view goes to beginning (current index : 0)
false--> i 'm trying to add a functionality to disable the list update continuously when the user click to a buttonCheckBox { id: checkBox text: "\uf0c1" checked: true onCheckedChanged: { if(checked) listViewDebug.scrollDebugAuto=true else { listViewDebug.scrollDebugAuto=false listViewDebug.scrollDebugIndex=listViewDebug.count-1 console.log("scroll debug index : "+listViewDebug.scrollDebugIndex) } } }
That's strange is when the model is updated from C++, the listView index is set to 0 !
When the scrollDebugAuto is true i have this on the log :qml: current index update :52
qml: current index update :0
qml: current index update :52
qml: current index :53
qml: save index : 0when is false
qml: current index update :0
qml: current index :89
qml: save index : 72we can see that the current index is set to 0 during C++ model update .
Do you have an idea how i can resolve this ? -
@Mickael-22 said in ListView issue when updated (current index set to 0):
Do you have an idea how i can resolve this ?
AFAIK, this is the normal behavior when using
QList<Object *>()
orQStringList()
as model, because each model update will generate a full new model.
If you wan't a smooth update, you have to useQAbstractItemModel
, cf. https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html -
@KroMignon Thanks for this explanations, it's more clear now.
I will have a look on QAbstractItemModel class, it just pity to add more complexity with this class to just keep list current index to it's value ! -
@Mickael-22 Yes QAbstractItemModel is not easy to use.
I use since many years now a template class create by Thomas Boutroue which creates an
QAbstractListModel
by introspection of the base QObject.
Take a look at Qt QML Models and Qt SuperMacros.Here are some explanations at Qt World Summit 2015:
https://resources.qt.io/videos/qtws15-lightning-talk-a-new-way-for-creating-qml-models-from-c-thomas-boutrouePerhaps this could help you.
-
This is an undocumented behavior of ListView. When the model is changed, currentIndex is set to 0, or -1 if the model if the empty.
https://code.woboq.org/qt5/qtdeclarative/src/quick/items/qquickitemview.cpp.html#239:
if (d->model) { ... if (isComponentComplete()) { ... setCurrentIndex(d->model->count() > 0 ? 0 : -1);
If you have the option, updating the model rather than changing to a new one is probably a better method.
-
@KroMignon Thanks a lot !
@jeremy_k
in the C++ code i just emit a signal that the list changed like this :m_debugList.append(new BleData(data,color,this)); emit debugListChanged();
class BleData : public QObject { Q_OBJECT public: explicit BleData(QObject *parent = nullptr); BleData(QString data,QString color = "black",QObject *parent = nullptr); Q_PROPERTY(QString data READ getData NOTIFY dataChanged) Q_PROPERTY(QString color READ getColor NOTIFY colorChanged) signals: void dataChanged(QString data); void colorChanged(QString color); public slots: QString getData() const; QString getColor() const; void addData(QString data,QString color="black"); private : QString m_data; QString m_color; };
I don't know how to proceed in another way
-
@Mickael-22 said in ListView issue when updated (current index set to 0):
@KroMignon Thanks a lot !
@jeremy_k
in the C++ code i just emit a signal that the list changed like this :m_debugList.append(new BleData(data,color,this)); emit debugListChanged();
That's the entire problem. Emitting the change signal for the list of QObjects says the entire list has changed, and should be treated as a new model.
The item models that @KroMignon refers to have signals to indicate changes within the model. If implementing a new QAbstractItemModel sounds like too much work, using a QStandardItemModel, or a QML ListView might work. QStringListView could also, with some changes to the delegate.
-
Thanks for this precisions.
i will have a look on the different options and let you know the more convenient way i will use