QTreeWidget insertTopLevelItem - 给定的索引未准确显示在树中?
-
22-09-2019 - |
题
我无法在特定索引处正确插入 QTreeWidgetItem,在这种情况下,我将从树中删除所有 QTreeWidgetItem,对它们的日期对象进行自定义排序,然后将它们插入回 QTreeWidget。
然而,在插入(即使一次一个)时,QTreeWidgetItem 没有插入到正确的位置。
下面的代码打印出来:
索引 0: 0
索引 0: 1 索引 1: 0
索引 0: 2 索引 1: 1 索引 2: 0
索引 0: 3 索引 1: 2 索引 2: 0 索引 3: 1
索引 0: 4 索引 1: 2 索引 2: 0 索引 3: 1 索引 4: 3
print 'index 0: ', self.indexOfTopLevelItem(childrenList[0])
self.insertTopLevelItem(0, childrenList[1])
print 'index 0: ', self.indexOfTopLevelItem(childrenList[0]), ' index 1: ',\
self.indexOfTopLevelItem(childrenList[1])
self.insertTopLevelItem(0, childrenList[2])
print 'index 0: ', self.indexOfTopLevelItem(childrenList[0]), ' index 1: ',\
self.indexOfTopLevelItem(childrenList[1]), ' index 2: ', \
self.indexOfTopLevelItem(childrenList[2])
self.insertTopLevelItem(0, childrenList[3])
print 'index 0: ', self.indexOfTopLevelItem(childrenList[0]), ' index 1: ',\
self.indexOfTopLevelItem(childrenList[1]), ' index 2: ',\
self.indexOfTopLevelItem(childrenList[2]), 'index 3: ',\
self.indexOfTopLevelItem(childrenList[3])
self.insertTopLevelItem(0, childrenList[4])
print 'index 0: ', self.indexOfTopLevelItem(childrenList[0]),\
' index 1: ', self.indexOfTopLevelItem(childrenList[1]),\
' index 2: ', self.indexOfTopLevelItem(childrenList[2]),\
'index 3: ', self.indexOfTopLevelItem(childrenList[3]),\
'index 4: ', self.indexOfTopLevelItem(childrenList[4])
解决方案
您可以进行自定义排序,无需重新填充树。您只需要重载 item 的“less”运算符即可。请注意,QT 通过查看项目的内容来计算出在单元格中绘制什么、它应该是什么大小、它应该包含什么文本
virtual QVariant data ( int column, int role ) const
创建项目时,您需要向构造函数提供一些字符串以供项目显示。该字符串被放入 data(.., QtCore.Qt.EditRole) 中,因此,将数据传递到构造函数中的等效操作是使用以下命令设置数据:
virtual void setData ( int column, int role, const QVariant & value)
在内部,数据只是一个数组,你可以放置任何你想要的东西,它的索引是角色(Qt.EditRole是2,Qt.ToolTipRole是3等),所以我们只是让一些角色来包含我们的数据,告诉比较运算符来比较这些值,并在我们设置 ValueRole 时告诉 setData 设置 DisplayRole。这是示例:
class TreeItem(QtGui.QTreeWidgetItem):
PythonValueRole = QtCore.Qt.UserRole
#values are list of python objects, that have __str__ and can be compared
def __init__(self, tree, values):
QtGui.QTreeWidgetItem.__init__(self, tree)
i = 0
for v in values:
self.setData(i, TreeItem.PythonValueRole, v)
i += 1
#overridden to simplify data assigning. When called with PythonValueRole, passes
#that object's string representation to DisplayRole and EditRole
def setData(self, col, role, value):
if role == TreeItem.PythonValueRole:
QtGui.QTreeWidgetItem.setData(self, col, TreeItem.PythonValueRole, value)
# sets DisplayRole and EditRole
QtGui.QTreeWidgetItem.setData(self, col, QtCore.Qt.EditRole, str(value))
QtGui.QTreeWidgetItem.setData(self, col, QtCore.Qt.DisplayRole, str(value))
else:
QtGui.QTreeWidgetItem.setData(self, col, role, value)
def __lt__(self, other):
c = self.treeWidget().sortColumn()
return self.data(c, TreeItem.PythonValueRole).toPyObject() <
other.data(c, TreeItem.PythonValueRole).toPyObject()
我测试过,效果很好。当然,您可以避免继承和覆盖 其 直接,因为我们有鸭子打字,所以使用 UserRole 本身来保存数据并设置数据直接使用 setData(col, role, val) 显示,或者甚至只保存编辑/显示角色中的文本并仅在比较时将其转换为日期时间,但看起来很丑。请注意,data() 包含 QVariant。当你设置数据时,你的 py 对象会自动转换,你需要调用 toPyObject() 来恢复原来的值。
其他提示
问题必须在您的代码中的其他地方。也许您没有正确删除这些物品?因为以下工作有效:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
app = QApplication(sys.argv)
tree = QTreeWidget()
items = [QTreeWidgetItem(['index %i' % i]) for i in range(5)]
for item in items:
tree.insertTopLevelItem(0, item)
print 'indexes: '
for item in items:
print tree.indexOfTopLevelItem(item),
tree.show()
app.exec_()