TableView seems to ignore dataChanged from QAbstractTableModel
-
Hello,
I'm having trouble getting a TableView to update it's display when a QAbstractTableModel emits dataChanged.
The intial data appears but then never updates in response to the dataChanged signal.The same QAbstractTableModel works fine in a separate Qt Widget application.
The table model has a timer that modifies the model and emits dataChanged.
The signal is definitely being emitted. I was able to connect to it from QML even but the view does not seem to update.Any ideas?
Thanks,
Jonahimport QtQuick import QtQuick.Controls Window { visible: true width: 512 height: 300 TableView { id: tableView anchors.fill: parent model: MyTableModel{ id: myModel } delegate: Rectangle{ id: cell required property var model Text { text: parent.model.display } } Connections { target: tableView.model onDataChanged: { console.log(myModel.toString()); } } } }
-
Ok, well it looks like views don't like dataChanged signals for ranges. I was emitting:
emit dataChanged(index(0,0), index(0, 5), {Qt::DisplayRole, Qt::EditRole} );
but if I limit it to a single column:
emit dataChanged(index(0,2), index(0, 2), {Qt::DisplayRole, Qt::EditRole} );
then the view reflects the change in that column!!
I'm curious why this is the case. I'll have to dig around in the source. Since I don't see dataChanged in the source for the tableView. It must be in a higher level class. The dataChanged connection in TreeView seemed to be unrelated to display data.
@Bob64 Yea I'm brand new to QML and I don't understand much of it yet. I was kind of trying different bits from different docs and examples. It did work without the property and just doing text: display.
The following article seems to suggest there is a benefit to have a required property:
https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.htmlSo I'm using this now:
component MyDelegate : Rectangle { required property string display Text { text: display } } TableView { id: tableView anchors.fill: parent model: MyTableModel{ id: myModel } delegate: MyDelegate {} Connections { target: tableView.model onDataChanged: { console.log(myModel.toString()); } } }
One other thing that caught me off guard was that.
This wasn't sufficient:
model: MyTableModel
I needed at least this:
model: MyTableModel {}
@j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:
Ok, well it looks like views don't like dataChanged signals for ranges
I have never used QML, but I would be "surprised" if this is the case. Googling I see no evidence of anyone else reporting this. Are you 100% sure your range is valid? And you do have a data change in an existing row, this is not an insert of a row? Just to check, have you implemented
setData()
in the model and that is what is emitting thedataChanged()
signal? -
Hello,
I'm having trouble getting a TableView to update it's display when a QAbstractTableModel emits dataChanged.
The intial data appears but then never updates in response to the dataChanged signal.The same QAbstractTableModel works fine in a separate Qt Widget application.
The table model has a timer that modifies the model and emits dataChanged.
The signal is definitely being emitted. I was able to connect to it from QML even but the view does not seem to update.Any ideas?
Thanks,
Jonahimport QtQuick import QtQuick.Controls Window { visible: true width: 512 height: 300 TableView { id: tableView anchors.fill: parent model: MyTableModel{ id: myModel } delegate: Rectangle{ id: cell required property var model Text { text: parent.model.display } } Connections { target: tableView.model onDataChanged: { console.log(myModel.toString()); } } } }
Glancing at the source it doesn't look like the QML TableView connects to dataChanged while the QML Tree View does. The TableView seems to favor some other interfaces over the QAbstractTableModel. Maybe I can get an idea from that or maybe I'll try the TreeView.
-
Glancing at the source it doesn't look like the QML TableView connects to dataChanged while the QML Tree View does. The TableView seems to favor some other interfaces over the QAbstractTableModel. Maybe I can get an idea from that or maybe I'll try the TreeView.
TableView does use dataChanged. Something else must be wrong on your end.
-
Hello,
I'm having trouble getting a TableView to update it's display when a QAbstractTableModel emits dataChanged.
The intial data appears but then never updates in response to the dataChanged signal.The same QAbstractTableModel works fine in a separate Qt Widget application.
The table model has a timer that modifies the model and emits dataChanged.
The signal is definitely being emitted. I was able to connect to it from QML even but the view does not seem to update.Any ideas?
Thanks,
Jonahimport QtQuick import QtQuick.Controls Window { visible: true width: 512 height: 300 TableView { id: tableView anchors.fill: parent model: MyTableModel{ id: myModel } delegate: Rectangle{ id: cell required property var model Text { text: parent.model.display } } Connections { target: tableView.model onDataChanged: { console.log(myModel.toString()); } } } }
@j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:
delegate: Rectangle{ id: cell required property var model Text { text: parent.model.display } }
Not an expert here, but I'm just trying to understand your delegate. What is the
required property
for? Also, ifdisplay
is a role exposed on your model, you should just be able to access it directly in the delegate:text: display
.I don't know if these things are actually related to any of the problems you see but they do look a bit unusual to me at least.
-
@j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:
delegate: Rectangle{ id: cell required property var model Text { text: parent.model.display } }
Not an expert here, but I'm just trying to understand your delegate. What is the
required property
for? Also, ifdisplay
is a role exposed on your model, you should just be able to access it directly in the delegate:text: display
.I don't know if these things are actually related to any of the problems you see but they do look a bit unusual to me at least.
Ok, well it looks like views don't like dataChanged signals for ranges. I was emitting:
emit dataChanged(index(0,0), index(0, 5), {Qt::DisplayRole, Qt::EditRole} );
but if I limit it to a single column:
emit dataChanged(index(0,2), index(0, 2), {Qt::DisplayRole, Qt::EditRole} );
then the view reflects the change in that column!!
I'm curious why this is the case. I'll have to dig around in the source. Since I don't see dataChanged in the source for the tableView. It must be in a higher level class. The dataChanged connection in TreeView seemed to be unrelated to display data.
@Bob64 Yea I'm brand new to QML and I don't understand much of it yet. I was kind of trying different bits from different docs and examples. It did work without the property and just doing text: display.
The following article seems to suggest there is a benefit to have a required property:
https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.htmlSo I'm using this now:
component MyDelegate : Rectangle { required property string display Text { text: display } } TableView { id: tableView anchors.fill: parent model: MyTableModel{ id: myModel } delegate: MyDelegate {} Connections { target: tableView.model onDataChanged: { console.log(myModel.toString()); } } }
One other thing that caught me off guard was that.
This wasn't sufficient:
model: MyTableModel
I needed at least this:
model: MyTableModel {}
-
Ok, well it looks like views don't like dataChanged signals for ranges. I was emitting:
emit dataChanged(index(0,0), index(0, 5), {Qt::DisplayRole, Qt::EditRole} );
but if I limit it to a single column:
emit dataChanged(index(0,2), index(0, 2), {Qt::DisplayRole, Qt::EditRole} );
then the view reflects the change in that column!!
I'm curious why this is the case. I'll have to dig around in the source. Since I don't see dataChanged in the source for the tableView. It must be in a higher level class. The dataChanged connection in TreeView seemed to be unrelated to display data.
@Bob64 Yea I'm brand new to QML and I don't understand much of it yet. I was kind of trying different bits from different docs and examples. It did work without the property and just doing text: display.
The following article seems to suggest there is a benefit to have a required property:
https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.htmlSo I'm using this now:
component MyDelegate : Rectangle { required property string display Text { text: display } } TableView { id: tableView anchors.fill: parent model: MyTableModel{ id: myModel } delegate: MyDelegate {} Connections { target: tableView.model onDataChanged: { console.log(myModel.toString()); } } }
One other thing that caught me off guard was that.
This wasn't sufficient:
model: MyTableModel
I needed at least this:
model: MyTableModel {}
@j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:
Ok, well it looks like views don't like dataChanged signals for ranges
I have never used QML, but I would be "surprised" if this is the case. Googling I see no evidence of anyone else reporting this. Are you 100% sure your range is valid? And you do have a data change in an existing row, this is not an insert of a row? Just to check, have you implemented
setData()
in the model and that is what is emitting thedataChanged()
signal? -
@j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:
delegate: Rectangle{ id: cell required property var model Text { text: parent.model.display } }
Not an expert here, but I'm just trying to understand your delegate. What is the
required property
for? Also, ifdisplay
is a role exposed on your model, you should just be able to access it directly in the delegate:text: display
.I don't know if these things are actually related to any of the problems you see but they do look a bit unusual to me at least.
using required properties is the recommended way to access model roles now : https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html#models
context properties like you suggested should be avoided.
I also agree with @JonB that there is something fishy here. dataChanged with ranges is supported. Implementing
setData
or not is irrelevant though, given that dataChanged is correctly emitted. -
using required properties is the recommended way to access model roles now : https://doc.qt.io/qt-6/qtquick-modelviewsdata-modelview.html#models
context properties like you suggested should be avoided.
I also agree with @JonB that there is something fishy here. dataChanged with ranges is supported. Implementing
setData
or not is irrelevant though, given that dataChanged is correctly emitted.@GrecKo yes, thank you - I have learned something today. I am still using Qt 5 and this doesn't seem to be emphasised as much in the docs there.
Having said that, OP was declaring
model
as arequired property
. My understanding now is that one should declare the roles that are being used. Is that correct? -
@j255 said in TableView seems to ignore dataChanged from QAbstractTableModel:
Ok, well it looks like views don't like dataChanged signals for ranges
I have never used QML, but I would be "surprised" if this is the case. Googling I see no evidence of anyone else reporting this. Are you 100% sure your range is valid? And you do have a data change in an existing row, this is not an insert of a row? Just to check, have you implemented
setData()
in the model and that is what is emitting thedataChanged()
signal? -