I have my custom list model where I put data which should be displayed on the QML view. But for some kind of reason the view in QML sometimes is updated normally, sometimes with previous data and sometimes updating is not performed.
Here is the function where I fill the model - this function is called from some other thread.
void MyScreen::fillListModel()
{
const QString SEPARATOR = " ";
myListModel->resetModel();
for (int i = 0; i < MAX_ROWS; ++i)
{
QString key = QString::fromUtf16(MyData::getParameterKey(i).c_str());
QString val = QString::fromUtf16(MyData::getParameterVal(i).c_str());
myListModel->addItem(key + SEPARATOR + val);
}
}
Implementation of model reset:
void BrowsingModelBase::resetModel()
{
beginResetModel();
m_items.clear();
endResetModel();
}
Implementation of addItem()
:
void BrowsingModelBase::addItem(const BrowsingItemModelBase &item)
{
int count = m_items.size();
beginInsertRows(QModelIndex(), count, count);
m_items.append(item);
endInsertRows();
}
Finally my QML file:
MyScreen {
Column {
id: myFlowList
y: 110
x: 220
ListView {
height:1000
spacing: 35;
model: myListModelRoot.myListModel
delegate: Text {
text: text1
}
}
}
}
The strange thing is that after loop with line
myListModel->addItem(key + SEPARATOR + val);
when I print logs with data from myListModel
it is filled with proper data, but the view is usually updated with previous data. Is it possible that data change signal is stuck somewhere? Any idea what is the solution?
Assuming that you call your model's methods from another thread, with the model being fundamentally not thread-safe, you have two options:
Make certain methods of your model thread-safe, or
Explicitly invoke the methods in a thread-safe fashion.
But first, you'd gain a bit of performance by adding all the items at once, as a unit. That way, the model will emit only one signal for all of the rows, instead of one signal per row. The views will appreciate it very much.
You should probably also have a method called
clear
instead ofresetModel
, since to reset a model has a much more general meaning: "change it so much that it's not worth emitting individual change signals". To reset a model does not mean "clear it"! Thus:Finally, following the 2nd approach of safely invoking the model's methods,
fillListModel
becomes as follows. See this answer for discussion ofpostTo
.Alternatively, following the first approach, you can make the
clear
andaddItems
methods thread-safe:You then need no changes to
fillListModel
, except to make it useaddItems
:The problem is most likely the fact that you are calling the
fillListModel()
method not from the main GUI thread. You can update the model from other threads but thebeginResetModel();
,endResetModel();
,beginInsertRows(QModelIndex(), count, count);
... methods have to be called in the main GUI thread.One way to call these method in GUI thread (maybe not the most efficient) is to :
Note that you will have to do the same for row insert methods as well. Or alternatively you could fill you model in the
resetModel()
method in between emitted signals.