Qtreewidget insertTopleVeM - Índice dado não exibido com precisão na árvore?
-
22-09-2019 - |
Pergunta
Não consigo inserir corretamente um QtreeWidgetItEm em um índice específico, neste caso estou removendo todos os QtreewidgetItems da árvore, fazendo uma classificação personalizada em seus objetos de data e depois os inserindo de volta no QtreeWidget.
No entanto, ao inserir (mesmo um de cada vez), o QtreeWidgetItEM não é inserido no local correto.
O código abaixo imprime:
ÍNDICE 0: 0
ÍNDICE 0: 1 ÍNDICE 1: 0
ÍNDICE 0: 2 ÍNDICE 1: 1 ÍNDICE 2: 0
ÍNDICE 0: 3 ÍNDICE 1: 2 ÍNDICE 2: 0 ÍNDICE 3: 1
ÍNDICE 0: 4 ÍNDICE 1: 2 ÍNDICE 2: 0 ÍNDICE 3: 1 ÍNDICE 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])
Solução
Você pode fazer sua classificação personalizada sem a necessidade de reabastecer a árvore. Você só precisa sobrecarregar o operador 'menos' do item. Observe que o QT descobre, o que desenhar na célula, que tamanho deveria ter, que texto deve conter, olhando no item
virtual QVariant data ( int column, int role ) const
Ao criar um item, você fornece alguma string para construtor para o item mostrar. Esta string é colocada em dados (.., qtcore.qt.editrole); portanto, o equivalente a transmitir dados para a Constutor é definir dados com:
virtual void setData ( int column, int role, const QVariant & value)
Internamente, os dados são apenas uma matriz, você pode colocar qualquer coisa jovem querer e os índices são papéis (qt.editrole é 2, qt.ToolTiprole é 3 etc.), por isso apenas deixamos alguma função conter nossos dados, informando a comparação Operador para comparar esses valores e informar o SetData Set DisplayRole quando definirmos nosso valor, digamos, valuerole. Aqui está a amostra:
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()
Eu testei, funciona bem. De Cource, você pode evitar herança e substituir lt Diretamente, como tínhamos digitação de pato, usamos a própria Userrole para manter seus dados e definir dados exibidos diretamente com o SetData (col, função, Val) ou até mesmo manter o texto na função de edição/exibição e convertê -lo apenas no DateTime enquanto comparava, Mas parece feio. Observe que Data () contém QVariant. Quando você define dados, seu objeto Py se converte automatizando automaticamente e você precisa ligar para topyObject () para obter seu valor de volta como era.
Outras dicas
O problema deve estar em outro lugar do seu código. Talvez você não esteja removendo os itens corretamente? Porque os seguintes trabalhos:
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_()