QAbstractItemModel методы index () и parent ()

Требуется реализовать метод QAbstractItemModel.parent(), иначе получится эта неприятная ошибка:

NotImplementedError: QAbstractItemModel.parent() is abstract and must be overridden

Помимо .parent(), метод index() также необходимо переопределить или указать:

NotImplementedError: QAbstractItemModel.index() is abstract and must be overridden

ВОПРОС: какова цель обоих методов и в чем разница в том, как они работают?

ИЗМЕНЕНО ПОЗЖЕ:

Пример метода .parent():

def getNodeFromIndex(self, index):    
    if index.isValid():
        node = index.internalPointer()
        if node:
            return node            
    return self.items


def parent(self, index):
    node = self.getNodeFromIndex(index)
    parentNode = node.getParent()
    if parentNode == self.items:
        return QtCore.QModelIndex()
    return self.createIndex(parentNode.row(), 0, parentNode)

Пример метода .index():

def index(self, row, column, parentIndex):
    parentNode = self.getNodeFromIndex(parentIndex)
    childNode = parentNode.getChildren(row)
    if childNode:            
        newIndex=self.createIndex(row, column, childNode)
        return newIndex
    else:
        return QtCore.QModelIndex()

Из бесконечного тестирования я действительно вижу, что .parent() метод вызывается только для QTableView элементов верхнего уровня. Хотя .index () вызывается для всех элементов: дочерние элементы верхнего уровня, дочерние элементы второго уровня, элементы-внуки третьего уровня и т. Д., Я также вижу, что оба возвращают QModelIndex со строкой, столбцом и переменной данных, «связанными» к нему. Похоже, что QModelIndexes, возвращаемые обоими методами, должны быть синхронизированы.

.parent() возвращает родительский элемент модели с заданным индексом. Если у элемента нет родителя, возвращается недопустимый QModelIndex. Обычное соглашение, используемое в моделях, которые предоставляют древовидные структуры данных, заключается в том, что только элементы в первом столбце имеют дочерние элементы. В этом случае при повторной реализации этой функции в подклассе столбец возвращенного QModelIndex будет равен 0. При повторной реализации этой функции в подклассе будьте осторожны, чтобы не вызывать QModelIndex функций-членов, таких как QModelIndex::parent(), поскольку индексы, принадлежащие вашей модели, будут просто назовите вашу реализацию, ведущую к бесконечной рекурсии.

.index() возвращает индекс элемента в модели, заданной данной строкой, столбцом и родительским индексом. При повторной реализации этой функции в подклассе вызовите createIndex(), чтобы сгенерировать индексы модели, которые другие компоненты могут использовать для ссылки на элементы в вашей модели.

Стоит отметить, что оба метода используют метод self.createIndex(row, column, dataVariable). Итак, они оба делают одно и то же: создают QModelIndexes. Я просто не понимаю, зачем нам нужны два метода, чтобы делать одно и то же! И это сложно отладить, так как кажется, что они работают в бесконечном цикле ....


person alphanumeric    schedule 10.01.2015    source источник
comment
Что мешает вам прочитать Qt документация по теме?   -  person ekhumoro    schedule 10.01.2015
comment
Привет, Эхуморо! Примеры документации Qt в основном написаны на C (по крайней мере, его учебник по MVC).   -  person alphanumeric    schedule 10.01.2015
comment
Из бесконечного тестирования я действительно вижу, что .parent() метод вызывается только для элементов QTableView верхнего уровня. В то время как .index() вызывается для всех элементов: дочерние элементы верхнего уровня, дочерние элементы второго уровня, элементы внуков третьего уровня и т. Д. Я также вижу, что оба возвращают QModelIndex со связанной с ним строкой, столбцом и переменной данных. Похоже, что QModelIndexes, возвращаемые обоими методами, должны быть синхронизированы.   -  person alphanumeric    schedule 10.01.2015
comment
.parent() возвращает родителя элемента модели с заданным индексом. Если у элемента нет родителя, возвращается недопустимый QModelIndex. Обычное соглашение, используемое в моделях, которые предоставляют древовидные структуры данных, заключается в том, что только элементы в первом столбце имеют дочерние элементы. В этом случае при повторной реализации этой функции в подклассе столбец возвращенного QModelIndex будет равен 0. При повторной реализации этой функции в подклассе будьте осторожны, чтобы избежать вызова функций-членов QModelIndex, таких как QModelIndex :: parent (), поскольку индексы принадлежат к вашей модели просто вызовет вашу реализацию, ведущую к бесконечной рекурсии.   -  person alphanumeric    schedule 10.01.2015
comment
.index() возвращает индекс элемента в модели, заданной данной строкой, столбцом и родительским индексом. При повторной реализации этой функции в подклассе вызовите createIndex (), чтобы сгенерировать индексы модели, которые другие компоненты могут использовать для ссылки на элементы в вашей модели.   -  person alphanumeric    schedule 10.01.2015
comment
Стоит отметить, что оба метода используют метод self.createIndex(row, column, dataVariable). Итак, они оба делают одно и то же: создают QModelIndexes. Я просто не понимаю, зачем нам нужны два метода, чтобы делать одно и то же! И это сложно отладить, так как кажется, что они работают в бесконечном цикле ...   -  person alphanumeric    schedule 10.01.2015
comment
Оставляйте комментарии, чтобы задавать вопросы постерам или давать небольшие пояснения. Я скопировал ваши комментарии к вашему сообщению, где вы должны были разместить их в первую очередь. Не стесняйтесь очищать и удалять ненужные комментарии.   -  person Oliver    schedule 12.01.2015


Ответы (1)


Эти методы определены абстрактно, чтобы заставить пользователя реализовать их при создании подклассов. Ваша модель не будет работать без их реализации, потому что они необходимы для определения структуры вашей модели.

Обычно, когда вы хотите создать иерархическую модель, вы должны реализовать методы index() и parent(). Для моделей таблиц и списков во многих случаях достаточно создать подклассы QAbstractListModel и QAbstractTableModel, которые имеют свои реализации по умолчанию этих двух методов.

Проще говоря, QAbstractItemModel.parent() возвращает родительский QModelIndex из дочернего элемента, а QAbstractItemModel.index() вызывается всякий раз, когда модели или представлению необходимо создать QModelIndex для определенного дочернего элемента (или элемента верхнего уровня, если родительский элемент является недопустимым QModelIndex).

person Nejat    schedule 10.01.2015
comment
Спасибо! Я пытаюсь разработать модель с возможностью расширения для QTreeView, если возникнет такая необходимость. - person alphanumeric; 10.01.2015
comment
Можно ли сказать, что .parent() методы используются для создания QModelIndex для элементов верхнего уровня. А .index() методы используются для создания QModelIndex для любых других элементов верхнего уровня? Или такое заявление было бы неверным? - person alphanumeric; 10.01.2015
comment
@Sputnix Нет, это совершенно неправильно. index() фактически используется для создания QModelIndex каждого элемента в модели. Это может быть элемент верхнего уровня или дочерний элемент. parent() используется для возврата родителя любого элемента. В иерархических моделях многие элементы на разных уровнях имеют родителей, и только элементы верхнего уровня не имеют родительского элемента, в котором для них должен быть возвращен недопустимый QModelIndex в parent(). - person Nejat; 10.01.2015
comment
Внутри метода .parent() я вижу (в моем исходном сообщении под # ОТРЕДАКТИРОВАННОЕ ПОЗЖЕ): если это индекс верхнего уровня, полученный в качестве аргумента, этот метод просто возвращает QtCore.QModelIndex(). Но если это не элемент верхнего уровня, этот .parent() метод идет дальше и создает новый QModelIndex, используя: self.createIndex(parentNode.row(), 0, parentNode), где parentNode - это переменная данных, которая связана с новым созданным QModelIndex. Итак ... он создает QModelIndexes ... Я действительно теряюсь с терминами, которые мы используем ... например, он возвращается ... откуда возвращается? Я действительно хотел бы понять - person alphanumeric; 10.01.2015
comment
Да, он создает QModelIndex родительского элемента для элемента и возвращается. Если элемент является элементом верхнего уровня, он создает недопустимый QModelIndex и возвращает его. - person Nejat; 10.01.2015
comment
Спасибо! Последний вопрос ... как node = index.internalPointer() работает? Что именно происходит, когда .internalPointer() вызывает index? - person alphanumeric; 10.01.2015
comment
internalPointer() возвращает структуру данных, связанную с заданным индексом. Это указатель на данные, которые вы передаете в качестве аргумента при вызове createIndex. - person Nejat; 10.01.2015
comment
Понятно! Еще раз спасибо! - person alphanumeric; 11.01.2015