Как QAbstractItemModel представляет дерево?

Мне все еще сложно понять представление элементов в QAbstractItemModel. Есть два метода, которые возвращают элементы QModelIndex, которые просто не имеют для меня никакого смысла.

QModelIndex QAbstractItemModel::index(int row, int column, const QModelIndex& index)

это первое. Какое представление передается этой функции? Я индексирую конкретный элемент дерева, для которого нужно создать индекс? Если да, то в чем смысл функции? Почему бы просто не вернуть индекс? Что представляют собой строка и столбец? Действительно ли index является родительским узлом, а функция возвращает конкретный индекс в зависимости от количества строк ниже этого родительского узла? Колонка здесь просто невозможна?

Когда используется переданный параметр строки, если когда-либо, относится ли строка 0 к самому индексу / родительскому узлу или к первому элементу под ним?

Второй,

QModelIndex QAbstractItemModel::parent(const QModelIndex& index) const

Похоже, этот метод вернет прямого родителя переданного индекса. Я работаю со структурой данных, которая по своей сути древовидная, но хранится в плоском массиве с элементами массива, содержащими информацию о глубине дерева, поэтому у прямого родителя всегда будет родитель с глубиной на 1 меньше, чем его собственная глубина. Но что в этом случае скармливают createIndex? На что ссылаются внутренняя строка, столбец и внутренний указатель QModelIndex? Учитывая используемую мной структуру на основе массивов, каким должен быть родительский элемент array [0]?

Я уже прочитал примеры Qt и документацию по этим темам и, похоже, не могу добиться прогресса в понимании того, как работают эти классы.


person SixDegrees    schedule 22.01.2017    source источник


Ответы (1)


QAbstractItemModel неспроста называют "абстрактным". Он не определяет и не применяет какой-либо конкретный способ хранения элементов модели, это полностью зависит от вас, разработчика подкласса QAbstractItemModel и реализации необходимых интерфейсов в вашем подклассе. Что QAbstractItemModel, так это интерфейсы, которые используются представлениями для связи с моделью. То, что он также как бы навязывает, является «ментальной моделью» того, как данные могут быть представлены в стандартных представлениях.

Вы можете думать о QAbstractItemModel как о ребенке, рожденном в семье дерева и стола. Представьте себе дерево: у вас есть группа элементов, каждый элемент может иметь свои собственные дочерние элементы, у них также могут быть свои дочерние элементы и так далее. Теперь представьте себе таблицу: у вас есть набор элементов, которые упорядочены в 2D-массив, который можно индексировать по строкам и столбцам. Теперь представьте, что у вас есть дерево, все элементы которого могут иметь несколько столбцов и, таким образом, выглядеть как строки таблицы. Итак, если вы, скажем, развернете какой-либо элемент дерева, о котором известно, что у него есть дочерние элементы, вы увидите таблицу - несколько дочерних элементов, расположенных в несколько строк + каждый из них имеет несколько столбцов. Я надеюсь, что эта ментальная модель поможет разобраться в интерфейсах QAbstractItemModel и, казалось бы, странного QModelIndex класса.

QModelIndex, как указано в официальной документации, используется для поиска элементов внутри модель. В первом приближении должно быть достаточно, чтобы индекс имел строку, столбец и родительский элемент, чтобы однозначно идентифицировать элемент в такой модели дерева строк. На самом деле QModelIndex позволяет вам делать даже больше: вы можете поместить некоторый указатель или некоторый внутренний идентификатор в индекс, если это упрощает ваш собственный код для идентификации элемента модели в ваших собственных структурах данных, используемых в вашем подклассе QAbstractItemModel.

Таким образом, методы, о которых вы спрашивали, делают примерно следующее:

  1. QAbstractItemModel :: index принимает строку, столбец и родительский < / strong> предполагаемого модельного элемента и возвращает QModelIndex соответствующий ему. Позже представление может использовать этот возвращенный объект QModelIndex для вызова, например, данных вашей модели, чтобы получить некоторые актуальные данные для отображения. Вы можете спросить, почему представление не запрашивает данные только по строке, столбцу и родительскому элементу? Что ж, теоретически это возможно, но если вы сделаете это через QModelIndex, вы, разработчик определенного подкласса модели, сможете использовать такие приемы, как внутренний указатель или внутренний идентификатор.
  2. QAbstractItemModel :: parent должен возвращать QModelIndex родительского элемента для представленного элемента. мимо пройденного в QModelIndex. Или просто недействителен QModelIndex, если у этого элемента нет родителя. Теперь вы можете задаться вопросом, как вы можете создать QModelIndex, который будет знать своего родителя, если QAbstractItemModel :: createIndex принимает строку, столбец и указатель или идентификатор, но не родительский QModelIndex? Ответ прост: QModelIndex, возвращаемый QAbstractItemModel::createIndex, содержит ссылку на объект модели, который его создал; поэтому, когда представление запрашивает QModelIndex своего родителя, этот вызов распространяется на модель, создавшую этот QModelIndex, т.е. вызывается QAbstractItemModel::parent. И теперь ваша модель должна использовать либо специальную индексацию, либо внутренний указатель, либо внутренний идентификатор, либо, возможно, какую-то сумасшедшую магию для идентификации родителя элемента, на который указывает переданный в QModelIndex.
person Dmitry    schedule 25.01.2017