Модели и представления в QML

Применение View/Model в QML

Последнее обновление: 12.01.2024

Как и в виджетах, в Qt Quick/QML также применяется паттерн View/Model, который состоит из трех компонентов:

  • Модель: содержит данные и их структуру

  • Представление: отображает данные

  • Делегат: определяет, как данные должны отображаться в представлении. Делегат также применяется для сохранения измененных данных обратно в модель

Паттерн View/Model в QML и Qt Quick

Qt Quick предоставляет ряд встроенных типов представлений:

  • ListView: располагает данные в виде списка

  • GridView: располагает данные в виде грида

  • TableView: располагает данные в виде таблицы

  • TreeView: располагает данные в виде дерева

  • PathView: располагает данные, используя геометрические пути (фигуры)

Для работы с представлениями в Qt Quick определен ряд классов моделей, основные из них:

  • ListModel: определяет данные в виде списка

  • TableModel: определяет данные в виде таблицы

  • DelegateModel: объединяет модель и делегат

  • ObjectModel: определяет набор данных, которые применяются в качестве модели

  • XmlListModel: использует данные в формате xml

Большинство моделей располагается в пакете " QtQml.Models", однако некоторые модели, например, TableModel, на момент написания текущей статьи имеют экспериментальный статус и поэтому располагаются в пакете "Qt.labs.qmlmodels". Отдельные типы моделей могут располагаться в других пакетах

Для связи представления с моделью класс представления определяет свойство model. Этому свойству передается объект модели. Для управления визуализацией данных модели типы представлений также определяют свойство delegate, которому передается шаблон данных в виде объекта Component или другого совместимомго типа.

В качестве модели для свойства model можно указать следующие данные:

  • Объект встроенного типа модели (например, ListModel, XmlListModel, ObjectModel и т.д.), который содержит данные

  • Объект класса C++, который унаследован от абстрактного класса QAbstractItemModel

  • Массив JavaScript

  • Число - количество создаваемых элементов

Число в качестве модели

Если свойству model представления передается число, то оно определяет количество элементов, которые создает делегат. В этом случае также устанавливается свойство delegate, которое и представляет делегат. В качестве значения ему передается объект Component (или объект иного совместимого типа), который представляет шаблон элемента представления. Стоит отметить, что число в model ограничено значением 100 000 000.

Создание списка на примере представления ListView:

import QtQuick

Window {
    width: 250
    height: 150
    visible: true
    title: "METANIT.COM"

    ListView {
        anchors.fill: parent
        model: 5
        delegate: Text {
            text: "Item " + index
        }
    }
}
Integer-based model в ListView в QML и Qt Quick

В данном случае создается пять элементов

model: 5

Для создания применяется делегат

delegate: Text {
    text: "Item " + index
}

То есть для каждого элемента создается элемент Text, в котором устанавливается свойство "text". По умолчанию через свойство "index" внутри делегата можно получить индекс создаваемого элемента.

Массив как модель данных

В качестве модели может выступать обычный массив JavaScript:

import QtQuick

Window {
    width: 250
    height: 150
    visible: true
    title: "METANIT.COM"

    ListView {
        anchors.fill: parent
        model: ["Tom", "Bob", "Sam"]
        delegate: Text {text: modelData}
    }
}

Здесь в качестве модели применяется массив из трех строк. Таким образом, для каждого элемента будет выполняться делегат, который создаст по одному элементу Text. Внутри делегата каждый элемент модели можно получить с помощью свойства modelData

Массив в качестве модели в ListView в QML и Qt Quick

Причем массив может представлять более сложные данные - объекты с определенными свойствами. В этом случае также через modelData можно обратиться к свойствам объекта:

import QtQuick

Window {
    width: 250
    height: 150
    visible: true
    title: "METANIT.COM"

    ListView {
        anchors.fill: parent
        model: [
            {name:"Tom", age:39},
            {name:"Bob", age:43},
            {name:"Sam", age:28}
        ]
        delegate: Text {text: modelData.name + " (" + modelData.age + ")"}
    }
}

В данном случае каждый объект в массиве сожержит два свойства: name и age, значения которых отображаются в элементе Text.

Массив сложных объектов в качестве модели в ListView в QML и Qt Quick

Применение встроенного типа модели

Для различных ситуаций Qt Quick представляет ряд моделей. Например, для создания списка можно использовать модель ListModel:

import QtQuick

Window {
    width: 250
    height: 150
    visible: true
    title: "METANIT.COM"

    ListModel {
        id: usersModel

        ListElement {
            name: "Tom"
            age: 39
        }
        ListElement {
            name: "Bob"
            age: 43
        }
        ListElement {
            name: "Sam"
            age: 28
        }
    }

    ListView {
        anchors.fill: parent
        model: usersModel
        spacing: 5
        delegate: Text {
            text: name + " (" + age + ")"
        }
    }
}
Массив сложных объектов в качестве модели в ListView в QML и Qt Quick

Модель определяется типом ListModel из пакета "QtQml.Models". Это не единственный тип модели, который мы можем использовать. При необходимости мы можем создавать свои типы моделей. ListModel — это простой контейнер элементов ListElement, каждое из которых содержит роли данных. Содержимое ListModel может быть определено динамически или явно в QML.

Тип ListElement представляет отдельный элемент списка в ListModel. ListItem определяется, как и другие элементы в QML, только вместо свойств содержит роли (согласно терминологии официальной документации). Например, в примере выше для каждого ListElement определяются две роли - "name" и "age". Имена ролей должны начинаться со строчной буквы и быть общими для всех элементов в данной модели. Значения должны быть простыми константами: строки, логические значения (true, false), числа или значения перечисления (например, AlignText.AlignHCenter). Таким образом, в примере выше определяются три элемента, каждый из которых представляет данные человека. Каждый элемент имеет две роли: name и age для хранения имени и возраста человека соответственно.

Делегат создает для каждого элемента модели элемент Text, у которого устанавливается свойство text:

delegate: Text {
    text: name + " (" + age + ")"
}

Внутри делегата мы можем обратиться к ролям текущего элемента модели по их имени - name и age.

ObjectModel

ObjectModel содержит визуальные элементы, которые будут использоваться в представлении. При применении этой модели представление не требует делегата, поскольку объектная модель уже содержит визуальный делегат (элементы). Например:

import QtQuick

Window {
    width: 250
    height: 150
    visible: true
    title: "METANIT.COM"

    ObjectModel {
        id: itemsModel
        Rectangle { height: 50; width: 80; color: "red" }
        Rectangle { height: 50; width: 80; color: "green" }
        Rectangle { height: 50; width: 80; color: "blue" }
    }

    ListView {
        anchors.fill: parent
        model: itemsModel
        spacing: 5
    }
}

Здесь объект ObjectModel содержит три прямоугольника. И при установке модели ListView отобразит эти прямоугольники:

ObjectModel в QML и Qt Quick
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850