是什么触发 QTreeView 在 QAbstractItemModel.data() 函数中请求 SizeHintRole
what triggers a QTreeView to ask for a SizeHintRole in the QAbstractItemModel.data() function
我已经使用 TreeViews
和 AbstractItemModels
制作了一些不同的应用程序,但我遇到了一些我不明白的事情。我意识到该视图正在调用模型的 data
函数,为项目请求 Size
,因为角色是 SizeHintRole (see Qt Documentation)。在所有其他情况下,我都不记得需要担心为 data
函数返回 size
。在下面的代码中,我错误地认为 data
只会查找列表中的项目,如果您取消注释第一行,视图将不显示任何内容,因为实际上视图正在请求 sizeHint
的指数。
我的问题是,什么情况下需要这样做?我以前从来不需要提供 sizeHint
,我不明白什么时候需要,什么时候不需要。
window当第一行被注释时
window当第一行启用时,因此忽略sizeHint请求
import sys
from PyQt5 import QtCore, QtWidgets
class TreeList:
def __init__(self):
self._items = list()
class TreeModel(QtCore.QAbstractItemModel):
def __init__(self, root, parent=None):
super().__init__(parent)
self.root = root
def index(self, row: int, column: int, parent: QtCore.QModelIndex = ...) -> QtCore.QModelIndex:
if not self.hasIndex(row, column, parent):
return QtCore.QModelIndex()
if not parent.isValid():
pointer = self.root # type: TreeList
child = pointer._items[row]
else:
child = None
return self.createIndex(row, column, child)
def addItem(self, layer):
row = len(self.root._items)
self.beginInsertRows(QtCore.QModelIndex(), row, row)
self.root._items.append(layer)
self.endInsertRows()
def parent(self, child: QtCore.QModelIndex) -> QtCore.QModelIndex:
return QtCore.QModelIndex()
def rowCount(self, parent: QtCore.QModelIndex = ...) -> int:
if parent.isValid():
return 0
else:
return len(self.root._items)
def columnCount(self, parent: QtCore.QModelIndex = ...) -> int:
return 1
def hasChildren(self, parent: QtCore.QModelIndex = ...) -> bool:
return False if parent.isValid() else True
def data(self, index: QtCore.QModelIndex, role: int = ...):
# return self.root._items[index.row()]
if role == QtCore.Qt.SizeHintRole:
print(index.isValid(), index.row(), index.column())
return QtCore.QSize(100, 20)
else:
return self.root._items[index.row()]
def flags(self, index: QtCore.QModelIndex):
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
class StackTreeView(QtWidgets.QTreeView):
def __init__(self, data=None, parent=None):
super().__init__(parent)
self.setModel(TreeModel(data))
def addItem(self, layer):
self.model().addItem(layer)
def test():
app = QtWidgets.QApplication(sys.argv)
data = TreeList()
data._items = ['one', 'two']
sys.excepthook = sys.__excepthook__
tree_view = StackTreeView(data)
tree_view.show()
tree_view.addItem('three')
tree_view.addItem('four')
sys.exit(app.exec_())
if __name__ == '__main__':
test()
默认为所有角色返回 self.root._items[index.row()]
毫无意义。您应该始终明确检查角色,并且只 return 一个适合 特定角色 的值。如果你没有特定于某个角色的数据,你应该在 PyQt 中 return None
(相当于 C++ 中的无效 QVariant
)。
有关基本要求的概述,请参阅 Model Subclassing Reference。
我已经使用 TreeViews
和 AbstractItemModels
制作了一些不同的应用程序,但我遇到了一些我不明白的事情。我意识到该视图正在调用模型的 data
函数,为项目请求 Size
,因为角色是 SizeHintRole (see Qt Documentation)。在所有其他情况下,我都不记得需要担心为 data
函数返回 size
。在下面的代码中,我错误地认为 data
只会查找列表中的项目,如果您取消注释第一行,视图将不显示任何内容,因为实际上视图正在请求 sizeHint
的指数。
我的问题是,什么情况下需要这样做?我以前从来不需要提供 sizeHint
,我不明白什么时候需要,什么时候不需要。
window当第一行被注释时
window当第一行启用时,因此忽略sizeHint请求
import sys
from PyQt5 import QtCore, QtWidgets
class TreeList:
def __init__(self):
self._items = list()
class TreeModel(QtCore.QAbstractItemModel):
def __init__(self, root, parent=None):
super().__init__(parent)
self.root = root
def index(self, row: int, column: int, parent: QtCore.QModelIndex = ...) -> QtCore.QModelIndex:
if not self.hasIndex(row, column, parent):
return QtCore.QModelIndex()
if not parent.isValid():
pointer = self.root # type: TreeList
child = pointer._items[row]
else:
child = None
return self.createIndex(row, column, child)
def addItem(self, layer):
row = len(self.root._items)
self.beginInsertRows(QtCore.QModelIndex(), row, row)
self.root._items.append(layer)
self.endInsertRows()
def parent(self, child: QtCore.QModelIndex) -> QtCore.QModelIndex:
return QtCore.QModelIndex()
def rowCount(self, parent: QtCore.QModelIndex = ...) -> int:
if parent.isValid():
return 0
else:
return len(self.root._items)
def columnCount(self, parent: QtCore.QModelIndex = ...) -> int:
return 1
def hasChildren(self, parent: QtCore.QModelIndex = ...) -> bool:
return False if parent.isValid() else True
def data(self, index: QtCore.QModelIndex, role: int = ...):
# return self.root._items[index.row()]
if role == QtCore.Qt.SizeHintRole:
print(index.isValid(), index.row(), index.column())
return QtCore.QSize(100, 20)
else:
return self.root._items[index.row()]
def flags(self, index: QtCore.QModelIndex):
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
class StackTreeView(QtWidgets.QTreeView):
def __init__(self, data=None, parent=None):
super().__init__(parent)
self.setModel(TreeModel(data))
def addItem(self, layer):
self.model().addItem(layer)
def test():
app = QtWidgets.QApplication(sys.argv)
data = TreeList()
data._items = ['one', 'two']
sys.excepthook = sys.__excepthook__
tree_view = StackTreeView(data)
tree_view.show()
tree_view.addItem('three')
tree_view.addItem('four')
sys.exit(app.exec_())
if __name__ == '__main__':
test()
默认为所有角色返回 self.root._items[index.row()]
毫无意义。您应该始终明确检查角色,并且只 return 一个适合 特定角色 的值。如果你没有特定于某个角色的数据,你应该在 PyQt 中 return None
(相当于 C++ 中的无效 QVariant
)。
有关基本要求的概述,请参阅 Model Subclassing Reference。