ListModel in C++ and append continuously from a thread



  • Hi,

    From the Object ListModel Example http://doc.qt.io/qt-5/qtquick-models-objectlistmodel-example.html
    I Want to continuously append rows to the list from a thread.

    After
    ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
    I can not append more.

    some help had been appreciated!

    /MJ


  • Moderators

    @qtMJ
    thats not possible. Using a list as a model is rather more static.
    You will need to implement a custom QAbstractListModel for example.
    Or assign a whole new list as a model.



  • Thanks for you reply!

    I found this AbstractItemModel Example,
    http://doc.qt.io/qt-5/qtquick-models-abstractitemmodel-example.html

    I passed
    AnimalModel model;
    to my thread, and I managed to add to the list, but the view only update my ListView if I resize the window.
    Is this right way to go, and how can I update my view?

    /MJ


  • Moderators

    @qtMJ
    seems like you are missing some necessary signals in your model implementation when adding new rows



  • @qtMJ Do you mean that when you scroll your list view you can't see your the newly added items but when you resize the window you can see them? Sounds like a problem in QML side. The AnimalModel example has this code:

    void AnimalModel::addAnimal(const Animal &animal)
    {
        beginInsertRows(QModelIndex(), rowCount(), rowCount());
        m_animals << animal;
        endInsertRows();
    }
    

    and if you call it to add animals to list it should send signals automatically and the view should be updated. You can try to catch the signal in QML:

    Connections{
    target: myModelObjectWhichWasSetAsContextProperty
    onRowsInserted: console.log("rows were inserted")
    }
    

    If it works there's something wrong with the view.



  • @qtMJ Another different solution could be to send signal from C++ when new item is added. You can catch it in QML, get the item from C++ in some compatible data form and add to the list using append(). But a C++ model is better IMO.



  • When I scroll the list by grab it with the mouse or resize, the list will update the new items.

    The only code I added to the example is my thread that I start in main.cpp before
    QQuickView view;

    And run like this (Here model is moved as a global, even tryed to pass it as pointer)

    void myThread::run()
    {
    int i=0;
    while (1) {
    model.addAnimal(Animal("Animal" + QString::number(++i), "Medium"));
    msleep(1000);
    }
    }

    And in my QML I just added

    Connections{
    target: myModel
    onRowsInserted: console.log("rows were inserted")
    }

    and the text shows up in my consol every second.



  • @qtMJ Then there's nothing wrong, that's expected behavior. You have to scroll the view, it's not scrolled automatically. You can catch ListView's add() signal and use positionViewAtIndex() or positionViewAtEnd().



  • @Eeli-K Ok thanks,
    I will try positionViewAtIndex()
    but just so you did understand me right...
    It is not that I can't see the items because they comes outside the window and don't scroll down
    automaticly.
    There are no item att all in the windows until I grab it or resize it.



  • I found another example at

    https://arunpkqt.wordpress.com/2016/12/08/qml-list-view-sort-and-filter/

    To my model I added from the example

    class FilterProxyModel : public QSortFilterProxyModel

    and in my main.cpp I changed to following code

    FilterProxyModel filterModel;
    filterModel.setSourceModel(&model);
    
    QQmlApplicationEngine engine;
    QQmlContext* ctxt = engine.rootContext();
    ctxt->setContextProperty("myModel", &filterModel);
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    

    And in my QML I changed to ApplicationWindow and put my ListView in a ColumnLayout.

    And now when it works as I wanted, I can continue and try to understand why...

    Thanks for all help and if you think this solution is good, I can mark this post as solved
    and continue with my project?

    /MJ



  • The correct solution is to not modify a model from an other thread.
    You could either use invokeMethod or emit a signal and connect it to a function in the main thread to add data to your model.



  • @GrecKo said in ListModel in C++ and append continuously from a thread:

    The correct solution is to not modify a model from an other thread.
    You could either use invokeMethod or emit a signal and connect it to a function in the main thread to add data to your model.

    @qtMJ Consider also whether you need a thread at all. If you need timed actions use QTimer. It's not a good programming practice to use while loop and sleep in a Qt application.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.