Я пытаюсь обернуть список в QAbstractItemModel в Python, чтобы позволить мне просматривать список в виде дерева, используя совершенство графического интерфейса, которое поставляется с PyQt. Если быть точным, я использую PyQt5 и Python 3.3.
Я попытался явно сгенерировать указатели на элементы списка, но потом у меня возникли проблемы с идентификацией родительских элементов. Я не назначаю их, и я не уверен, как и если PyQt назначит их, когда вы выполняете createIndex. Затем я решил переписать код, чтобы явно идентифицировать элементы, к которым можно получить доступ, используя индексы (значения строк), например. задан вложенный список ["A",["a",[1,2,3]],"B","C",["b",[4,5,6],"d"]] I затем может указывать на 5, используя [4,1,1], затем родитель извлекается с использованием того же списка за вычетом последнего элемента, [4,1].
Моя проблема заключается в следующем. Метод CREATEINDEX приводит к сбою кода, когда я использую список, сгенерированный из значений строки. Мой минимальный неработающий пример (MBE) приведен ниже. Раскомментируйте две строки с «return self.createIndex(row,col,ptr)» в них, чтобы увидеть разбивку, которую я описываю.
from PyQt5.QtGui import QFont, QColor
from PyQt5.QtCore import QAbstractItemModel, QModelIndex, Qt, QAbstractListModel, QAbstractTableModel, QSize, QVariant
from PyQt5.QtWidgets import QApplication, QTreeView, QTableView, QListView
class NodeTree(QAbstractItemModel) :
def __init__(self,parent,data) :
super(NodeTree,self).__init__(parent)
self.data = data
def rowCount(self, parent = QModelIndex()) :
# int rowCount (self, QModelIndex parent = QModelIndex())
if parent.isValid() :
data = self.data
for idx in parent.internalPointer() :
data = data[idx]
return len(data)
else :
return len(self.data)
def columnCount(self, parent = QModelIndex()) :
# int columnCount (self, QModelIndex parent = QModelIndex())
return 1
def data(self, index = QModelIndex(), role = None) :
# QVariant data (self, QModelIndex index, int role = Qt.DisplayRole)
if role == 0 :
if index.isValid() :
return str(index.internalPointer())
else :
return "No Data"
return None
def index(self,row,col, parent = QModelIndex()):
# QModelIndex index (self, int row, int column, QModelIndex parent = QModelIndex())
# QModelIndex createIndex (self, int arow, int acolumn, int aid)
# QModelIndex createIndex (self, int arow, int acolumn, object adata = 0)
if parent.isValid() :
ptr = [parent.internalPointer(),row]
# return self.createIndex(row,col,ptr)
return QModelIndex()
else :
ptr = [row]
# return self.createIndex(row,col,ptr)
return QModelIndex()
return QModelIndex()
def parent(self, child = QModelIndex()):
# QObject parent (self)
if child.isValid() :
print(child.internalPointer())
return QModelIndex()
if __name__ == "__main__" :
# http://blog.mathieu-leplatre.info/filesystem-watch-with-pyqt4.html
import sys
app = QApplication(sys.argv)
TreeView = QTreeView()
TreeModel = NodeTree(TreeView, [['A',['a',1]],['C','D'],['E','F']])
TreeView.setModel(TreeModel)
TreeView.show()
app.exec_()
Чего я не понимаю, так это того, как QModelIndex создается в CREATEINDEX и почему он падает для списка, сгенерированного на лету в методе INDEX. Для меня INTERNALPOINTER должен быть сохранен между вызовами, и передача списка должна быть в порядке.
Другая вещь, которая меня смущает, это когда и почему вызываются родитель и индекс. Насколько я понимаю, индекс проходит вниз по дереву, а родительский - вверх. Таким образом, вызов INDEX идентифицирует дочерний элемент родителя в (строка, столбец), а PARENT является дочерним элементом и определяет родителя. Делается ли это со ссылкой на внутренний указатель? Если да, то почему QmodelIndex поддерживает собственный метод PARENT. Кажется, что Qt поддерживает собственное внутреннее дерево, которое устанавливает иерархию между элементами на основе вызовов между индексом и родителем. То есть всегда есть два дерева: одно для Моей модели и одно на дисплее.