“父母”的概念是怎样的?在 QAbstractListModel 中有意义吗?
我有一个 QAbstractListModel 的子类,它是 QML ListView 的模型(使用 PySide6)。列表的每一行都有一个复选框,当用户选中/取消选中某个框时,它会使用我对 setData()
的重写来更新列表模型该行中的布尔值,这会按预期工作。我还有应该选择/清除列表中所有复选框的按钮。
我的模型子类提供了以下方法来选择全部,当用户点击 Button
或应用程序中发生其他事情时可以调用该方法:
def select_all(self):
for i in range(self.rowCount()):
row = self._rows[i]
row['selected'] = True
# Emitting this for each row works...
self.dataChanged.emit(self.index(i), self.index(i), [])
# ... whereas emitting just one signal for ALL rows does NOT work
# self.dataChanged.emit(self.index(0), self.index(self.rowCount()), [])
正如您从注释中看到的,我需要发出 <每行的 code>dataChanged 以便更新 ListView
中的复选框。发射一次信号并使用 topLeft
和 bottomRight
参数不会更新 < code>ListView(但模型数据已正确更新)。
根据文档,由 QAbstractItemModel
提供的 dataChanged
信号(并由 QAbstractListModel
继承)具有 此警告:
如果项目属于同一父项,则受影响的项目是在 topLeft 和 BottomRight 之间(含)的项目。如果这些项目没有相同的父项,则行为未定义。
我似乎遇到了这样的情况:模型中的行没有相同的父级,因此“行为未定义”。我认为这是有道理的,因为我从来没有做任何事情来为我的任何行建立父/子关系。我还看到了这个答案,这意味着当topLeft
和bottomRight时Qt的行为不同
索引是相同的。所以,我想更好地理解这一点,并且我有几个问题:
- 我是否正确地认为这个父概念是在为每一行发出时确实工作的原因不适用于所有行?
- 父/子关系的概念是否只对扩展 QAbstractItemModel 而不是 QAbstractListModel 的树状模型有意义?这对于列表有意义吗?
- 如果它确实对列表有意义,那么“父级”是什么,“子级”又是什么?我如何配置 QAbstractListModel 的子类,以便可以发出一次 dataChanged 来更新多行?
谢谢!
I have a subclass of QAbstractListModel
that is the model for a QML ListView
(using PySide6). Each row of the list has a checkbox in it, and when the user checks/unchecks a box, it updates a boolean in that row of the listmodel using my override of setData()
, which works as expected. I also have Button
s that should select/clear all of the checkboxes in the list.
My model subclass provides the following method to select all, which can be called when the user hits the Button
or when other things happen in the application:
def select_all(self):
for i in range(self.rowCount()):
row = self._rows[i]
row['selected'] = True
# Emitting this for each row works...
self.dataChanged.emit(self.index(i), self.index(i), [])
# ... whereas emitting just one signal for ALL rows does NOT work
# self.dataChanged.emit(self.index(0), self.index(self.rowCount()), [])
As you can see from the comments, I need to emit dataChanged
for each row in order for the checkboxes in the ListView
to be updated. Emitting the signal once and using the topLeft
and bottomRight
parameters does not update the state of the checkboxes in the ListView
(but the model data is correctly updated).
According to the documentation, the dataChanged
signal provided by QAbstractItemModel
(and inherited by QAbstractListModel
) has this caveat:
If the items are of the same parent, the affected ones are those between topLeft and bottomRight inclusive. If the items do not have the same parent, the behavior is undefined.
It seems likely that I'm running into the scenario where the rows in my model do NOT have the same parent, and therefore, "the behavior is undefined." I suppose that makes sense, because I never do anything to establish a parent/child relationship for any of my rows. I also saw this answer which implies that Qt behaves differently when the topLeft
and bottomRight
indices are the same. So, I would like to understand this better, and I have a few questions:
- Am I correct that this parent concept is the reason this does work when emitted for each row and does not work for all rows?
- Is the concept of a parent/child relationship only meaningful for tree-like models that would extend
QAbstractItemModel
instead ofQAbstractListModel
? Does it make any kind of sense for a list? - If it does make sense for a list, then what would be the "parent" and what would be the "child?" How would I configure a subclass of
QAbstractListModel
such thatdataChanged
can be emitted once to update multiple rows?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
虽然 Qt 项视图的基本实现只是在
topLeft
和bottomRight
索引不匹配时不加区别地更新视图(因此您可以只提供两个“随机”,但仍然同级索引),索引不仅必须共享一个共同的父级索引(对于一维和二维模型来说始终是无效索引),而且必须都是有效的。对于这一行,第二个索引无效:
这是因为索引始终从 0 开始,最后一行的索引实际上是
rowCount - 1
。虽然它们理论上是兄弟姐妹,但由于它们共享相同的父级(根索引的父级无效,因为它是无效索引的父级),因此它们不是两者都有效。因此,正确的语法是:
请注意,roles 参数是可选的,并且已经默认为空列表(C++ 中的 QVector),因此除非您确实想要指定更改的角色,否则不需要提供那个。
While the base implementation of Qt item views just updates indiscriminately the view whenever the
topLeft
andbottomRight
indexes doesn't match (so you can just provide two "random", but still sibling indexes), the indexes must not only share a common parent (which for one and two dimensional models is always an invalid index), but also both valid.With this line, the second index is not valid:
This is because the indexes are always 0-based, and the index of the last row is actually
rowCount - 1
. While they theoretically are siblings, since they share the same parent (the parent of a root index is invalid, as it is the parent of an invalid index), they are not both valid.So, the correct syntax is:
Note that the
roles
argument is optional and already defaults to an empty list (QVector in C++), so unless you actually want to specify the changed roles, you don't need to provide that.