QAbstractListModel - dataChanged
-
wrote on 10 Feb 2017, 12:45 last edited by goxx00 2 Oct 2017, 12:48
Hey I am a newbie in Qt so please be gentle :)
i write an application on the raspi which should display some measure sizes in real time. I get the values from a socket coonection to a PC. This connection is the base on my connection-class. This class runs in a second Thread. To display the values i have wrote an other class(page) which inherits from an QAbstractListModel. I display this Model in a GridView . My problem is when i change the values of the page class it should emit dataChanged() but my GUI doesnt changed.
I tried the update the GridView with my own signal, by setting the model of the gridview to zero and than back to the data-model. But that was to much for my little raspi and i got an huge delay.
So whats my Mistake?my setData function:
bool Page::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(index.row()<0||index.row()>labels_p.size())
return false;
if(role=Qt::EditRole)
{
int row = index.row();
labels_p[row].setvalue(value.toString().toStdString());
emit dataChanged(QModelIndex(),QModelIndex());
return true;
}
return false;}
-
Hey I am a newbie in Qt so please be gentle :)
i write an application on the raspi which should display some measure sizes in real time. I get the values from a socket coonection to a PC. This connection is the base on my connection-class. This class runs in a second Thread. To display the values i have wrote an other class(page) which inherits from an QAbstractListModel. I display this Model in a GridView . My problem is when i change the values of the page class it should emit dataChanged() but my GUI doesnt changed.
I tried the update the GridView with my own signal, by setting the model of the gridview to zero and than back to the data-model. But that was to much for my little raspi and i got an huge delay.
So whats my Mistake?my setData function:
bool Page::setData(const QModelIndex &index, const QVariant &value, int role)
{
if(index.row()<0||index.row()>labels_p.size())
return false;
if(role=Qt::EditRole)
{
int row = index.row();
labels_p[row].setvalue(value.toString().toStdString());
emit dataChanged(QModelIndex(),QModelIndex());
return true;
}
return false;}
-
wrote on 10 Feb 2017, 13:06 last edited by
Thanks for your reply.
I didnt work either. -
Hope you have put this code whenever you change the data in the model.
beginInsertRows(QModelIndex(), rowCount(), rowCount()); .... .... endInsertRows();
This should automatically update you UI.
-
wrote on 10 Feb 2017, 13:18 last edited by
I used this function in my add function and this also doesn't update my GUI. But i will try.
void Page::addLabel(const Label &label) { beginInsertRows(QModelIndex(), rowCount(),rowCount()); labels_p<<label; endInsertRows(); }
-
wrote on 10 Feb 2017, 14:52 last edited by
Thanks.
QVariant Page::data(const QModelIndex &index, int role) const { if(index.row() <0 || index.row() >= labels_p.count()) return QVariant(); const Label &label = labels_p[index.row()]; if (role==LabelnameRole) return label.labelname(); else if (role==ValueRole) return label.value(); else if (role==UnitRole) return label.unit(); else if (role==DisplaytypRole) return label.displaytyp(); else if (role==DisplaysizeRole) return label.displaysize(); return QVariant(); }
-
wrote on 13 Feb 2017, 07:52 last edited by
Any advices ?
-
wrote on 13 Feb 2017, 09:53 last edited by Julien B
Try replacing
if(role==Qt::EditRole)
byif(role==ValueRole)
in yoursetData
method.Are you sure your data is properly writed in
labels_p
in your code (checked with the debugger or a simple qDebug)?How do you write your
value
data in your qml? -
wrote on 13 Feb 2017, 12:16 last edited by
You haven't shown your qml code, the problem might be there, in the view or delegate.
-
Try replacing
if(role==Qt::EditRole)
byif(role==ValueRole)
in yoursetData
method.Are you sure your data is properly writed in
labels_p
in your code (checked with the debugger or a simple qDebug)?How do you write your
value
data in your qml?wrote on 13 Feb 2017, 14:16 last edited by@Julien-B said in QAbstractListModel - dataChanged:
Try replacing if(role==Qt::EditRole) by if(role==ValueRole) in your setData method.
Are you sure your data is properly writed in labels_p in your code (checked with the debugger or a simple qDebug)?Now the values get updated in the labels_p. You were right. Before I corrected the typing error it worked too :D
-
wrote on 13 Feb 2017, 14:23 last edited by goxx00
GridView { id:contentView anchors.fill: parent cellWidth: 200 cellHeight: 105 flow: GridView.FlowLeftToRight layoutDirection: Qt.LeftToRight verticalLayoutDirection: GridView.TopToBottom model: dataModel delegate: gridViewtemplate }
...
Component { id: gridViewtemplate Rectangle { width: 190 height: 85 color: "#4c4c4c" Label { id:lname anchors.horizontalCenter: parent.horizontalCenter color: "#cccccc" anchors.margins: 5 anchors.top: parent.top text: labelname font.pixelSize: 20 } Label { anchors.left: parent.left color: "#cccccc" anchors.bottom: parent.bottom anchors.margins: 5 text: value font.pixelSize: 25 Label { anchors.left: parent.right color: "#cccccc" anchors.verticalCenter: parent.verticalCenter anchors.margins: 5 text: unit font.pixelSize: 10 } } } }
In my main.cpp I set the context property datamodel to an object of my Page class.
engine.rootContext()->setContextProperty("dataModel",connector.data2);
connector is the class where i implemented my sockets and where I have the data2-object, which is a Page object. I am aiming for displaying the data2 object in the gridview.
The connector runs in a second thread. -
GridView { id:contentView anchors.fill: parent cellWidth: 200 cellHeight: 105 flow: GridView.FlowLeftToRight layoutDirection: Qt.LeftToRight verticalLayoutDirection: GridView.TopToBottom model: dataModel delegate: gridViewtemplate }
...
Component { id: gridViewtemplate Rectangle { width: 190 height: 85 color: "#4c4c4c" Label { id:lname anchors.horizontalCenter: parent.horizontalCenter color: "#cccccc" anchors.margins: 5 anchors.top: parent.top text: labelname font.pixelSize: 20 } Label { anchors.left: parent.left color: "#cccccc" anchors.bottom: parent.bottom anchors.margins: 5 text: value font.pixelSize: 25 Label { anchors.left: parent.right color: "#cccccc" anchors.verticalCenter: parent.verticalCenter anchors.margins: 5 text: unit font.pixelSize: 10 } } } }
In my main.cpp I set the context property datamodel to an object of my Page class.
engine.rootContext()->setContextProperty("dataModel",connector.data2);
connector is the class where i implemented my sockets and where I have the data2-object, which is a Page object. I am aiming for displaying the data2 object in the gridview.
The connector runs in a second thread.wrote on 13 Feb 2017, 14:29 last edited byThis post is deleted! -
GridView { id:contentView anchors.fill: parent cellWidth: 200 cellHeight: 105 flow: GridView.FlowLeftToRight layoutDirection: Qt.LeftToRight verticalLayoutDirection: GridView.TopToBottom model: dataModel delegate: gridViewtemplate }
...
Component { id: gridViewtemplate Rectangle { width: 190 height: 85 color: "#4c4c4c" Label { id:lname anchors.horizontalCenter: parent.horizontalCenter color: "#cccccc" anchors.margins: 5 anchors.top: parent.top text: labelname font.pixelSize: 20 } Label { anchors.left: parent.left color: "#cccccc" anchors.bottom: parent.bottom anchors.margins: 5 text: value font.pixelSize: 25 Label { anchors.left: parent.right color: "#cccccc" anchors.verticalCenter: parent.verticalCenter anchors.margins: 5 text: unit font.pixelSize: 10 } } } }
In my main.cpp I set the context property datamodel to an object of my Page class.
engine.rootContext()->setContextProperty("dataModel",connector.data2);
connector is the class where i implemented my sockets and where I have the data2-object, which is a Page object. I am aiming for displaying the data2 object in the gridview.
The connector runs in a second thread. -
wrote on 14 Feb 2017, 10:50 last edited by
It shows nothing and in the application output occur no errors.
When I refresh the context property everytime I change something, then the model gets displayed. -
wrote on 14 Feb 2017, 14:29 last edited by
When I update the context property after adding the labels it works. But this shows me that my addLabel function has a mistake or do i have to emit a signal when i add an item to my QList ?
I thought the insertRows function do that.Thanks a lot for your help :)
-
When I update the context property after adding the labels it works. But this shows me that my addLabel function has a mistake or do i have to emit a signal when i add an item to my QList ?
I thought the insertRows function do that.Thanks a lot for your help :)
wrote on 14 Feb 2017, 16:14 last edited by@goxx00 Basically the data() method should work because data is shown once. Unless you want to edit the values through the GUI (make them user editable) you don't need the setData function. You can just read or receive the values from the socket, store them in some form and then decide in your reading/receiving code what kind of signal should be emitted to notify the view about the changes. If the amount of rows stays the same, emit dataChanged with the indexes of the first and the last changed row. If rows are added, call begin/endInsertRows(). If much of the data is changed and the amount of rows changes, it's easiest to call begin/endResetModel().
When the view receives a signal it automatically decides how to fetch and update the visible data. In any case it calls your model's data() function.
I assume you have read the Subclassing section of the documentation and implemented rowCount and roleNames functions (probably it wouldn't work the first time unless you haven't).
-
wrote on 15 Feb 2017, 06:53 last edited by
Thank you very much. For sure, I have read the section and implemented the rowCount(), the flags() and the roleNames() functions. I hope I will get it it now.
THANK YOU VERY MUCH!!!
-
wrote on 15 Feb 2017, 10:08 last edited by
Ok I am not ready yet :D I have the next problem maybe you can help me with it.
When I add an Item to the QList, with the addLabel function I get an error:QObject::connect:: Cannot queue arguments of type 'QQmlChangeSet' (Make sure 'QQmlChangeSet' is registered using qRegisterMetaType().)
I searched for a solution but I didnt found sth. that worked.
I thin k it has to do with the fact that the object is in another Thread than the GUI.
1/19