En esta página

Uso de modelos C++ con Qt Quick Vistas

Datos proporcionados en un modelo C++ personalizado

Los modelos pueden definirse en C++ y luego ponerse a disposición de QML. Esto resulta útil para exponer a QML modelos de datos C++ existentes o conjuntos de datos complejos.

Una clase de modelo C++ puede definirse como QStringList, QVariantList, QObjectList o QAbstractItemModel. Las tres primeras son útiles para exponer conjuntos de datos más sencillos, mientras que QAbstractItemModel proporciona una solución más flexible para modelos más complejos.

Modelo basado en QStringList

Un modelo puede ser un simple QStringList, que proporciona el contenido de la lista a través del rol modelData.

Aquí se muestra un ListView con un delegado que hace referencia al valor de su elemento del modelo utilizando el rol modelData:

ListView {
    width: 100
    height: 100
    required model

    delegate: Rectangle {
        required property string modelData
        height: 25
        width: 100
        Text { text: parent.modelData }
    }
}

Una aplicación Qt puede cargar este documento QML y establecer el valor de myModel en QStringList:

    QStringList dataList = {
        "Item 1",
        "Item 2",
        "Item 3",
        "Item 4"
    };

    QQuickView view;
    view.setInitialProperties({{ "model", QVariant::fromValue(dataList) }});

El código fuente completo de este ejemplo está disponible en examples/quick/models/stringlistmodel dentro del directorio de instalación de Qt.

Nota: No hay forma de que la vista sepa que el contenido de QStringList ha cambiado. Si el QStringList cambia, será necesario reiniciar el modelo estableciendo de nuevo la propiedad model de la vista.

Modelo basado en QVariantList

Un modelo puede ser un único QVariantList, que proporciona el contenido de la lista a través del rol modelData.

La API funciona igual que con QStringList, como se muestra en la sección anterior.

Nota: No hay forma de que la vista sepa que el contenido de un QVariantList ha cambiado. Si el QVariantList cambia, será necesario reiniciar el modelo estableciendo de nuevo la propiedad model de la vista.

Modelo basado en QObjectList

También se puede utilizar como modelo una lista de valores QObject*. Un QList<QObject*> proporciona las propiedades de los objetos de la lista como roles.

La siguiente aplicación crea una clase DataObject con valores Q_PROPERTY que serán accesibles como roles con nombre cuando un QList<DataObject*> se exponga a QML:

class DataObject : public QObject
{
    Q_OBJECT

    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
    Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
    ...
};

int main(int argc, char ** argv)
{
    QGuiApplication app(argc, argv);

    const QStringList colorList = {"red",
                                   "green",
                                   "blue",
                                   "yellow"};

    const QStringList moduleList = {"Core", "GUI", "Multimedia", "Multimedia Widgets", "Network",
                                    "QML", "Quick", "Quick Controls", "Quick Dialogs",
                                    "Quick Layouts", "Quick Test", "SQL", "Widgets", "3D",
                                    "Android Extras", "Bluetooth", "Concurrent", "D-Bus",
                                    "Gamepad", "Graphical Effects", "Help", "Image Formats",
                                    "Location", "Mac Extras", "NFC", "OpenGL", "Platform Headers",
                                    "Positioning", "Print Support", "Purchasing", "Quick Extras",
                                    "Quick Timeline", "Quick Widgets", "Remote Objects", "Script",
                                    "SCXML", "Script Tools", "Sensors", "Serial Bus",
                                    "Serial Port", "Speech", "SVG", "UI Tools", "WebEngine",
                                    "WebSockets", "WebView", "Windows Extras", "XML",
                                    "XML Patterns", "Charts", "Network Authorization",
                                    "Virtual Keyboard", "Quick 3D", "Quick WebGL"};

    QList<QObject *> dataList;
    for (const QString &module : moduleList)
        dataList.append(new DataObject("Qt " + module, colorList.at(rand() % colorList.length())));

    QQuickView view;
    view.setResizeMode(QQuickView::SizeRootObjectToView);
    view.setInitialProperties({{ "model", QVariant::fromValue(dataList) }});
    ...

El QObject* está disponible como propiedad modelData. Por comodidad, las propiedades del objeto también están disponibles directamente en el contexto del delegado. Aquí, view.qml hace referencia a las propiedades DataModel en el delegado ListView:

ListView {
    id: listview
    width: 200; height: 320
    required model
    ScrollBar.vertical: ScrollBar { }

    delegate: Rectangle {
        width: listview.width; height: 25

        required color
        required property string name

        Text { text: parent.name }
    }
}

Nótese el uso de la propiedad color. Puedes requerir propiedades existentes declarándolas como required en un tipo derivado.

El código fuente completo de este ejemplo está disponible en examples/quick/models/objectlistmodel dentro del directorio de instalación de Qt.

Nota: No hay forma de que la vista sepa que el contenido de QObjectList ha cambiado. Si el QObjectList cambia, será necesario reiniciar el modelo estableciendo de nuevo la propiedad model de la vista.

Subclase de QAbstractItemModel

Se puede definir un modelo subclasificando QAbstractItemModel. Este es el mejor enfoque si tienes un modelo más complejo que no puede ser soportado por los otros enfoques. QAbstractItemModel también puede notificar automáticamente a una vista QML cuando cambian los datos del modelo.

Las funciones de una subclase QAbstractItemModel pueden exponerse a QML reimplementando QAbstractItemModel::roleNames().

A continuación se muestra una aplicación con una subclase QAbstractListModel denominada AnimalModel, que expone los roles type y sizes. Reimplementa QAbstractItemModel::roleNames() para exponer los nombres de los roles, de forma que se pueda acceder a ellos a través de QML:

class Animal
{
public:
    Animal(const QString &type, const QString &size);
    ...
};

class AnimalModel : public QAbstractListModel
{
    Q_OBJECT
public:
    enum AnimalRoles {
        TypeRole = Qt::UserRole + 1,
        SizeRole
    };

    AnimalModel(QObject *parent = nullptr);
    ...
};

QHash<int, QByteArray> AnimalModel::roleNames() const {
    QHash<int, QByteArray> roles;
    roles[TypeRole] = "type";
    roles[SizeRole] = "size";
    return roles;
}

int main(int argc, char ** argv)
{
    QGuiApplication app(argc, argv);

    AnimalModel model;
    model.addAnimal(Animal("Wolf", "Medium"));
    model.addAnimal(Animal("Polar bear", "Large"));
    model.addAnimal(Animal("Quoll", "Small"));

    QQuickView view;
    view.setResizeMode(QQuickView::SizeRootObjectToView);
    view.setInitialProperties({{"model", QVariant::fromValue(&model)}});
    ...

Este modelo se muestra mediante un delegado de ListView que accede a los roles de tipo y tamaño:

ListView {
    width: 200; height: 250

    required model

    delegate: Text {
        required property string type
        required property string size

        text: "Animal: " + type + ", " + size
    }
}

Las vistas QML se actualizan automáticamente cuando cambia el modelo. Recuerde que el modelo debe seguir las reglas estándar para cambios de modelo y notificar a la vista cuando el modelo ha cambiado utilizando QAbstractItemModel::dataChanged(), QAbstractItemModel::beginInsertRows(), etc. Consulte la referencia Model subclassing para obtener más información.

El código fuente completo de este ejemplo está disponible en examples/quick/models/abstractitemmodel dentro del directorio de instalación de Qt.

QAbstractItemModel presenta una jerarquía de tablas, pero las vistas proporcionadas actualmente por QML sólo pueden mostrar datos de listas. Para mostrar las listas hijas de un modelo jerárquico, utilice el tipo QML DelegateModel, que proporciona las siguientes propiedades y funciones para su uso con modelos de listas del tipo QAbstractItemModel:

Exposición de modelos de datos C++ a QML

Los ejemplos anteriores utilizan propiedades requeridas en la vista para establecer los valores del modelo directamente en los componentes QML. Una alternativa es registrar la clase de modelo C++ como tipo QML (véase Definición de tipos QML desde C++). Esto permite crear las clases modelo directamente como tipos dentro de QML:

C++
class MyModel : public QAbstractItemModel
{
    Q_OBJECT
    QML_ELEMENT

    // [...]
}
QML
MyModel {
    id: myModel
}
ListView {
    width: 200; height: 250
    model: myModel
    delegate: Text {
        required property string someProperty
        text: someProperty
    }
}

Consulte Escribir extensiones QML con C++ para obtener más información sobre cómo escribir tipos QML en C++.

Modificación de los datos del modelo

Además de los métodos roleNames() y data(), los modelos editables deben reimplementar el método setData para guardar los cambios en los datos existentes del modelo. La siguiente versión del método comprueba si el índice del modelo dado es válido y el role es igual a Qt::EditRole:

bool EditableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.isValid() && role == Qt::EditRole) {
        // Set data in model here. It can also be a good idea to check whether
        // the new value actually differs from the current value
        if (m_entries[index.row()] != value.toString()) {
            m_entries[index.row()] = value.toString();
            emit dataChanged(index, index, { Qt::EditRole, Qt::DisplayRole });
            return true;
        }
    }
    return false;
}

Nota: Es importante emitir la señal dataChanged() después de guardar los cambios.

A diferencia de las vistas de elementos de C++ como QListView o QTableView, el método setData() debe invocarse explícitamente desde delegados QML siempre que sea apropiado. Esto se hace simplemente asignando un nuevo valor a la propiedad del modelo correspondiente.

ListView {
    anchors.fill: parent
    model: EditableModel {}
    delegate: TextField {
        width: ListView.view.width
        text: model.edit
        onAccepted: model.edit = text
    }
}

Nota: El rol edit es igual a Qt::EditRole. Véase roleNames() para los nombres de roles incorporados. Sin embargo, los modelos de la vida real suelen registrar roles personalizados.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.