PDA

View Full Version : ListView not being updated at runtime to follow the model



ustulation
14th June 2013, 21:43
Hi,
In our new project we have decided to use qml for the 1st time. Having spent sometime learning qt quick 1.0 in Qt 5.0, we suddenly have Qt 5.1 coming up which focuses on qml on desktops - what we need. Since 5.1 is still beta it is buggy (for QQuickView and in general QWindow maximize is not available - https://bugreports.qt-project.org/browse/QTBUG-31258). I want to know if the following issue is a bug or is the result of wrong coding on my part:
I make a class derived from QAbstractListModel and re-implement the necessary functions. I create an object of it, fill in some initial data into the model (all beginInsertRows etc done) and then pass it (the object) to qml via setContextProperty. For qt 5.1 with quick 1.0 I use QDeclarativeView. For qt 5.1 with quick 2.0 I use QQuickView. Once qml is 'shown' by show() command, I spawn a std::thread in which I pass the reference of the Model object. The thread keeps adding data to the model via direct call to Model's addData(..) function (which has beginInsertRows etc) using the passed reference every 'x' milliseconds. Meanwhile in the main thread QApplication's exec() would have started.

Problem: Using qt 5.1 quick 1.0 (QDeclarativeView) there is no problem - the ListView (UI) updates fine and keeps growing showing it is indeed following the model. Using quick 2.0 (QQuickView) breaks this behaviour. There is no update of the UI other than the initial data set into the model (described before). If I resize or imitate a flick with the mouse then suddenly all data contained upto that point is shown but again things halt there. I get the following listed in the Application Output pane in QtCreator:
QObject::connect: Cannot queue arguments of type 'QQmlChangeSet'
(Make sure 'QQmlChangeSet' is registered using qRegisterMetaType().)
I don't know what QQmlChangeSet is. However if I use QThread derived class and re-implement run() to do the same, but instead of passing the refernece of Model's object I emit signal which is caught by the Model's addData(..) function which I've now turned into a slot, then everything works fine again and the ListView UI grows in number of rows. Is this expected? If so then why (ie., what is wrong with the former approach)?

wysota
15th June 2013, 08:12
Your code is invalid. You cannot modify the model from within a worker thread. If you really have to use a thread, then emit a signal from it and connect it to a slot in the model that will perform the addition from the main thread.

ustulation
15th June 2013, 09:45
Finally you come to my rescue :)


Your code is invalid.
Why does it work with Qt Quick 1.0?


You cannot modify the model from within a worker thread. If you really have to use a thread, then emit a signal from it and connect it to a slot in the model that will perform the addition from the main thread.
Yes i guessed that because as stated, when i used the QThread way (similar to what you suggest), everything worked fine. Why can't model be updated in a worker thread? It's not a UI component. Could you please also give me a link to the documentation where this is stated? It's not in QAbstractItemModel doc.

wysota
15th June 2013, 12:39
Why does it work with Qt Quick 1.0?
No idea, it shouldn't. But QtQuick 2 and QtQuick 1 have a totally different implementation, maybe that's the reason.


Yes i guessed that because as stated, when i used the QThread way (similar to what you suggest), everything worked fine.
It doesn't matter if you use QThread or std::thread. The issue remains the same.


Why can't model be updated in a worker thread? It's not a UI component.
The basic idea is that the same resource cannot be accessed by more than one thread at the same time without proper synchronisation. The real problem in this particular case is a bit different (cross-thread signals and slots) but the original issue remains the same. You simply shouldn't ever try to do this.


Could you please also give me a link to the documentation where this is stated? It's not in QAbstractItemModel doc.

Go to QObject docs and search for "thread affinity".