listView changes are updated only when delegates are destroyed

  • I have created a c++ model in qml, mostly following "Using C++ Models in QML {tutorial}"( There is a qml list view connected with a c++ abstractlistmodel which intern used data from a c++ data class. very similar to the tutorial. I have created appendItem, removeItem functions in the c++ data class with the appropriate signals.

    The listView works fine for adding and removing list items via the c++ back-end class. However, when I make changes to existing items those changes are not reflected in the listView. At first I thought I needed to emit some signal from the data class to tell the model that data has been modified, but later I found that when the item updates itself if i scroll down and then back up.
    I know that listView destroys delegates when its outside of the view, which indicates that the underlying model is being modified but that change is not reflected immediately. its seems to only happen when the delegate is destroyed. is there a way to get the delegates to update? I have tried forceLayout(), and it doesn't work.
    thanks for your time.

  • Moderators

    @lionking_dexi said in listView changes are updated only when delegates are destroyed:

    is there a way to get the delegates to update?

    Yes, you have to emit dataChanged() from your model.

  • @sierdzio Thank you for your prompt response. As per the tutorial the dataChanged() signal is set up inside function setData(const QModelIndex &index, const QVariant &value, int role).
    How do i trigger this signal from the data class.
    With Reference to the tutorial in my post, the data is updated through a function in the ToDoList class , but the setData() is in the ToDoListModel class. I am stuck on how to connect the two.
    again thank you for your time.

  • @lionking_dexi
    The setData() method should emit dataChanged(), with appropriate parameters. If you call the base QAbstractItemModel::dataChanged() it will do it for you; if you reimplement in setData() without calling the base method you must do the emit yourself explicitly:

    When reimplementing the setData() function, this signal must be emitted explicitly.

    Because it's a signal, it doesn't matter which class you are in. The emit should come from wherever the setData() is defined; other classes can hook onto the signal with a slot even if signal & slot are in different classes.

  • @JonB Thank you for your explanation. I understand what i need to do, but i need a little help in making the right signals and slots. My project was setup using the "Using C++ Models in QML {tutorial}" as a guide. here the ToDoList class is set as the data in ToDoListModel class.
    In the ToDoList Calss there are:
    1.appendItem() function, which emits the signals preItemAppended() and postItemAppended()
    2.removeItem() funciton, which emits the signals preItemRemoved() and postItemRemoved()
    [these work fine]
    3.similar to the appendItem() and removeItem() I am trying to make a setItemAt() function that will modify the existing data. but there was no steps in the tutorial to indicate how i could notify the model to emit the dataChanged() signal. I tried making my own signal in the data class and a slot in model class but i couldn't figure out how to connect them. the main function has a ToDoList object but no ToDoListModel object (ToDoListModel is just registered to qml). i am only familiar with using the connect(*sender,signal,*receiver, slot) function to connect.
    I suspect that it has something to do with the
    'Q_PROPERTY(ToDoList *list READ list WRITE setList NOTIFY listChanged)'
    line in the ToDoListModel header file. following the tutorial I removed the NOTIFY listChanged part.
    summary:which signal do i need to emit from the data class(ToDoList) to have the model class (ToDoListModel) emit the dataChanged() signal?

Log in to reply