开发者

QTreeWidget insertTopLevelItem - index given not accurately displayed in Tree?

I am unable to properly insert a QTreeWidgetItem at a specific index, in this case I am removing all QTreeWidgetItems from the tree, doing a custom sort on their Date Objects and then inserting them back into the QTreeWidget.

However, upon inserting (even one at a time) the QTreeWidgetItem is not inserted into the correct place.

The code below prints out:

index 0: 0

index 0: 1 index 1: 0

index 0: 2 index 1: 1 index 2: 0

index 0: 3 index 1: 2 index 2: 0 index 3: 1

index 0: 4 index 1: 2 index 2: 0 index 3: 1 index 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开发者_Go百科: ', 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])


You can do your custom sort without a need to refill tree. You just need to overload item's 'less' operator. Note, that QT figures out, what to draw in the cell, what size it should be, what text should it contain, by looking in item's

virtual QVariant data ( int column, int role ) const

when you create an item, you provide some string to constructor for item to show. This string is placed into data(.., QtCore.Qt.EditRole), so, the equivalent of passing data into constuctor is to set data with:

virtual void setData ( int column, int role, const QVariant & value)

Internally, data is just an array, you can place anything youn want, and indexes of it are roles (Qt.EditRole is 2, Qt.ToolTipRole is 3 etc.), so we just let some role to contain our data, tell comparison operator to compare these values, and tell setData set DisplayRole when we set our, let's say, ValueRole. Here is the sample:

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

I've tested, it works fine. Of cource, you can avoid inheritance and override lt directly, since we had duck typing, use UserRole itself to hold your data and set data do display directly with setData(col, role, val), or even hold only text in edit/display role and convert it in datetime only while comparing, but it seems ugly. Note, that data() contains QVariant. When you set data, your py object automatcally converts, and you need to call toPyObject() to get your value back as it was.


The problem must be elsewhere in your code. Maybe you aren't removing the items properly? Because the following works:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜