0

我无法在特定索引处正确插入 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])
4

2 回答 2

2

您可以进行自定义排序,而无需重新填充树。您只需要重载 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 等等),所以我们只是让一些角色来包含我们的数据,告诉比较运算符来比较这些值,并在我们设置我们的值时告诉 setData 设置 DisplayRole,比方说,ValueRole。这是示例:

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()

我测试过,效果很好。当然,您可以避免继承并直接覆盖lt,因为我们有鸭子类型,使用 UserRole 本身来保存您的数据并使用 setData(col, role, val) 直接显示设置数据,甚至在编辑/显示中只保存文本角色并仅在比较时将其转换为日期时间,但看起来很难看。请注意,data() 包含 QVariant。当你设置数据时,你的 py 对象会自动转换,你需要调用 toPyObject() 来恢复原来的值。

于 2010-03-26T15:16:17.940 回答
2

问题必须在您的代码中的其他地方。也许您没有正确删除项目?因为以下工作:

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_()
于 2010-03-26T18:11:34.623 回答