En esta página

Modelos y vistas en Qt Quick

La mayoría de las aplicaciones necesitan dar formato a los datos y mostrarlos. Qt Quick tiene la noción de modelos, vistas y delegados para mostrar los datos. Modularizan la visualización de datos para dar al desarrollador o diseñador control sobre los diferentes aspectos de los datos. Un desarrollador puede cambiar una vista de lista por una vista de cuadrícula con pocos cambios en los datos. Del mismo modo, encapsular una instancia de los datos en un delegado permite al desarrollador dictar cómo presentar o manejar los datos.

  • Modelo: contiene los datos y su estructura. Existen varios tipos de QML para crear modelos.
  • Vista - un contenedor que muestra los datos. La vista puede mostrar los datos en una lista o en una cuadrícula.
  • Delegado - dicta cómo deben aparecer los datos en la vista. El delegado toma cada unidad de datos del modelo y la encapsula. Los datos son accesibles a través del delegado. El delegado también puede volver a escribir datos en modelos editables (por ejemplo, en un TextField's onAccepted Handler).

Para visualizar los datos, vincule la propiedad model de la vista a un modelo y la propiedad delegate a un componente o a otro tipo compatible.

Visualización de datos con vistas

Las vistas son contenedores de colecciones de elementos. Tienen muchas funciones y pueden personalizarse para satisfacer requisitos de estilo o comportamiento.

El conjunto básico de tipos gráficos de Qt Quick incluye una serie de vistas estándar:

Estos tipos tienen propiedades y comportamientos exclusivos de cada tipo. Visite su documentación respectiva para obtener más información.

Además, Qt Quick Controls contiene algunas vistas y delegados extra que son estilizados de acuerdo al estilo de la aplicación, por ejemplo HorizontalHeaderView y VerticalHeaderView.

Decoración de vistas

Las vistas permiten la personalización visual a través de propiedades de decoración como las propiedades header, footer, y section. Al vincular un objeto, normalmente otro objeto visual, a estas propiedades, las vistas son decorables. Un pie de página puede incluir un tipo Rectangle que muestre los bordes o una cabecera que muestre un logotipo en la parte superior de la lista.

Supongamos que un club concreto quiere decorar su lista de socios con los colores de su marca. La lista de socios está en un model y el delegate mostrará el contenido del modelo.

ListModel {
    id: nameModel
    ListElement { name: "Alice" }
    ListElement { name: "Bob" }
    ListElement { name: "Jane" }
    ListElement { name: "Harry" }
    ListElement { name: "Wendy" }
}
Component {
    id: nameDelegate
    Text {
        required property string name
        text: name
        font.pixelSize: 24
        width: ListView.view.width
    }
}

El club puede decorar la lista de socios vinculando objetos visuales a las propiedades header y footer. El objeto visual puede definirse en línea, en otro archivo o en un tipo Component.

ListView {
    anchors.fill: parent
    clip: true
    model: nameModel
    delegate: nameDelegate
    header: bannercomponent
    footer: Rectangle {
        width: parent.width; height: 30;
        gradient: clubcolors
    }
    highlight: Rectangle {
        color: "lightgray"
    }
}

Component {     //instantiated when header is processed
    id: bannercomponent
    Rectangle {
        id: banner
        width: parent.width; height: 50
        gradient: clubcolors
        border {color: "#9EDDF2"; width: 2}
        Text {
            anchors.centerIn: parent
            text: "Club Members"
            font.pixelSize: 32
        }
    }
}
Gradient {
    id: clubcolors
    GradientStop { position: 0.0; color: "#8EE2FE"}
    GradientStop { position: 0.66; color: "#7ED2EE"}
}

Manejo del ratón y del tacto

Las vistas gestionan el arrastre y el desplazamiento de su contenido, pero no la interacción táctil con los delegados individuales. Para que los delegados reaccionen a la entrada táctil, por ejemplo, para establecer el currentIndex, el delegado debe proporcionar un MouseArea con la lógica de manejo táctil adecuada.

Tenga en cuenta que si highlightRangeMode se establece en StrictlyEnforceRange, el índice actual se verá afectado al arrastrar o mover la vista, ya que la vista siempre se asegurará de que currentIndex se encuentre dentro del rango de resaltado especificado.

Secciones del ListView

ListView Los contenidos se pueden agrupar en secciones, donde los elementos relacionados de la lista se etiquetan según sus secciones. Además, las secciones pueden decorarse con delegados.

Una lista puede contener una lista que indique los nombres de las personas y el equipo al que pertenecen.

ListModel {
    id: nameModel
    ListElement { name: "Alice"; team: "Crypto" }
    ListElement { name: "Bob"; team: "Crypto" }
    ListElement { name: "Jane"; team: "QA" }
    ListElement { name: "Victor"; team: "QA" }
    ListElement { name: "Wendy"; team: "Graphics" }
}
Component {
    id: nameDelegate
    Text {
        required property string name
        text: name;
        font.pixelSize: 24
        anchors.left: parent.left
        anchors.leftMargin: 2
    }
}

El tipo ListView tiene la propiedad adjunta section que puede combinar tipos adyacentes y relacionados en una sección. El section.property determina qué propiedad de tipo lista utilizar como secciones. La section.criteria puede dictar cómo se muestran los nombres de las secciones y la section.delegate es similar a la propiedad delegate de las vistas.

ListView {
    anchors.fill: parent
    model: nameModel
    delegate: nameDelegate
    focus: true
    highlight: Rectangle {
        color: "lightblue"
        width: parent.width
    }
    section {
        property: "team"
        criteria: ViewSection.FullString
        delegate: Rectangle {
            color: "#b0dfb0"
            width: parent.width
            height: childrenRect.height + 4
            Text { anchors.horizontalCenter: parent.horizontalCenter
                font.pixelSize: 16
                font.bold: true
                text: section
            }
        }
    }
}

Delegados de vista

Las vistas necesitan un delegado para representar visualmente un elemento de una lista. Una vista visualizará cada elemento de la lista según el modelo definido por el delegado. Los elementos de un modelo son accesibles a través de la propiedad index así como de las propiedades del elemento.

Component {
    id: petdelegate
    Text {
        id: label
        font.pixelSize: 24
        text: index === 0 ? type + " (default)" : type

        required property int index
        required property string type
    }
}

Posicionamiento de los delegados de vista

El tipo de vista determinará cómo se posicionan los elementos. ListView posicionará los elementos en línea recta, dependiendo de orientation, mientras que GridView puede disponerlos en una cuadrícula de 2 dimensiones. No se recomienda enlazar directamente en x y y, ya que el comportamiento de diseño de la vista siempre tendrá prioridad sobre cualquier enlace posicional.

Acceso a vistas y modelos desde delegados

La vista de lista a la que está vinculado el delegado es accesible desde el delegado a través de la propiedad ListView.view. Del mismo modo, la propiedad GridView GridView.view está disponible para los delegados. El modelo correspondiente y sus propiedades, por tanto, están disponibles a través de ListView.view.model. Además, cualquier señal o método definido en el modelo también es accesible.

Este mecanismo es útil cuando se desea utilizar el mismo delegado para varias vistas, por ejemplo, pero se desea que las decoraciones u otras características sean diferentes para cada vista, y que estos ajustes diferentes sean propiedades de cada una de las vistas. Del mismo modo, puede ser interesante acceder o mostrar algunas propiedades del modelo.

En el siguiente ejemplo, el delegado muestra la propiedad idioma del modelo, y el color de uno de los campos depende de la propiedad color_fruta de la vista.

Rectangle {
     width: 200; height: 200

    ListModel {
        id: fruitModel
        property string language: "en"
        ListElement {
            name: "Apple"
            cost: 2.45
        }
        ListElement {
            name: "Orange"
            cost: 3.25
        }
        ListElement {
            name: "Banana"
            cost: 1.95
        }
    }

    Component {
        id: fruitDelegate
        Row {
            id: fruit
            required property string name
            required property real cost
            Text {
                text: " Fruit: " + fruit.name
                color: fruit.ListView.view.fruit_color
            }
            Text {
                text: " Cost: $" + fruit.cost
            }
            Text {
                text: " Language: " + fruit.ListView.view.model.language
            }
        }
    }

    ListView {
        property color fruit_color: "green"
        model: fruitModel
        delegate: fruitDelegate
        anchors.fill: parent
    }
}

Modelos

Los datos se proporcionan al delegado a través de roles de datos con nombre a los que el delegado puede vincularse. Aquí hay un ListModel con dos roles, tipo y edad, y un ListView con un delegado que se une a estos roles para mostrar sus valores:

import QtQuick

Item {
    width: 200
    height: 250

    ListModel {
        id: myModel
        ListElement { type: "Dog"; age: 8; noise: "meow" }
        ListElement { type: "Cat"; age: 5; noise: "woof" }
    }

    component MyDelegate : Text {
        required property string type
        required property int age
        text: type + ", " + age
        // WRONG: Component.onCompleted: () => console.log(noise)
        // The above line would cause a ReferenceError
        // as there is no required property noise,
        // and the presence of the required properties prevents
        // noise from being injected into the scope
    }

    ListView {
        anchors.fill: parent
        model: myModel
        delegate: MyDelegate {}
    }
}

En la mayoría de los casos deberías usar propiedades requeridas para pasar datos del modelo a tus delegados. Si un delegado contiene propiedades requeridas, el motor QML comprobará si el nombre de una propiedad requerida coincide con el de un rol del modelo. Si es así, esa propiedad se vinculará al valor correspondiente del modelo.

En raras ocasiones, es posible que desee transferir las propiedades del modelo a través del contexto QML en lugar de como propiedades obligatorias. Si no hay propiedades requeridas en su delegado, los roles nombrados se proporcionan como propiedades de contexto:

import QtQuick

Item {
    width: 200; height: 250

    ListModel {
        id: myModel
        ListElement { type: "Dog"; age: 8 }
        ListElement { type: "Cat"; age: 5 }
    }

    Component {
        id: myDelegate
        Text { text: type + ", " + age }
    }

    ListView {
        anchors.fill: parent
        model: myModel
        delegate: myDelegate
    }
}

Las propiedades de contexto son invisibles para las herramientas e impiden que el compilador deQt Quick optimice el código. Las propiedades de contexto son invisibles para las herramientas e impiden que el compilador optimice el código. No hay forma de rellenar explícitamente el contexto QML desde QML. Si tu componente espera que los datos se pasen a través del contexto QML, sólo puedes utilizarlo en lugares en los que el contexto adecuado esté disponible a través de medios nativos. Esto puede ser su propio código C++ o las implementaciones específicas de los elementos circundantes. Por el contrario, las propiedades requeridas pueden establecerse de varias formas desde QML o a través de medios nativos. Por lo tanto, pasar datos a través del contexto QML reduce la reutilización de sus componentes.

Si hay un conflicto de nombres entre las propiedades del modelo y las del delegado, se puede acceder a las funciones con el nombre cualificado del modelo. Por ejemplo, si un tipo Text tuviera propiedades (no obligatorias) de tipo o edad, el texto del ejemplo anterior mostraría esos valores de propiedad en lugar de los valores de tipo y edad del elemento del modelo. En este caso, se podría hacer referencia a las propiedades como model.type y model.age para garantizar que el delegado muestra los valores de propiedad del elemento del modelo. Para que esto funcione, necesitas requerir una propiedad model en tu delegado (a menos que estés usando propiedades de contexto).

El delegado también dispone de una función de índice especial que contiene el índice del elemento del modelo. Ten en cuenta que este índice se establece en -1 si el elemento se elimina del modelo. Si se vincula a la función de índice, asegúrese de que la lógica tiene en cuenta la posibilidad de que el índice sea -1, es decir, que el elemento ya no sea válido. (Normalmente el elemento se destruirá en breve, pero es posible retrasar la destrucción delegada en algunas vistas a través de una propiedad adjunta delayRemove ).

Recuerda que puedes utilizar enteros o matrices como modelo:

Repeater {
    model: 5
    Text {
        required property int modelData
        text: modelData
    }
}
Repeater {
    model: ["one", "two", "three"]
    Text {
        required property string modelData
        text: modelData
    }
}

Tales modelos proporcionan una pieza singular y anónima de datos a cada instancia del delegado. Acceder a esta pieza de datos es la razón principal para utilizar modelData, pero otros modelos también proporcionan modelData.

El objeto proporcionado a través del rol model tiene una propiedad con un nombre vacío. Esta propiedad anónima contiene el modelData. Además, el objeto proporcionado a través del rol model tiene otra propiedad llamada modelData. Esta propiedad está obsoleta y también contiene el modelData.

Además del rol model, se proporciona un rol modelData. El rol modelData contiene los mismos datos que la propiedad modelData y la propiedad anonymous del objeto proporcionado a través del rol model.

Las diferencias entre el rol de modelo y los distintos medios para acceder a modelData son las siguientes:

  • Los modelos que no tienen roles con nombre (como los enteros o un array de cadenas) tienen sus datos proporcionados a través del rol modelData. En este caso, el rol modelData no contiene necesariamente un objeto. En el caso de un modelo entero, contendría un número entero (el índice del elemento actual del modelo). En el caso de una matriz de cadenas, contendría una cadena. El rol del modelo todavía contiene un objeto, pero sin ninguna propiedad para roles con nombre. Sin embargo, el modelo todavía contiene sus propiedades habituales modelData y anonymous.
  • Si el modelo sólo tiene un rol con nombre, el rol modelData contiene los mismos datos que el rol con nombre. No es necesariamente un objeto y no contiene el rol con nombre como una propiedad con nombre como lo haría normalmente. El rol modelo aún contiene un objeto con el rol nombrado como propiedad, y las propiedades modelData y anonymous en este caso.
  • Para modelos con múltiples roles, el rol modelData sólo se proporciona como una propiedad requerida, no como una propiedad de contexto. Esto se debe a la compatibilidad con versiones anteriores de Qt.

La propiedad anónima en el modelo te permite escribir limpiamente delegados que reciben tanto los datos de su modelo como el nombre del rol al que deben reaccionar como propiedades desde el exterior. Puedes proporcionar un modelo sin o con un solo rol con nombre, y una cadena vacía como rol. Entonces, un enlace que simplemente acceda a model[role] hará lo que esperas. No tienes que añadir código especial para este caso.

Nota: Los roles model, index y modelData no son accesibles si el delegado contiene propiedades requeridas, a menos que también tenga propiedades requeridas con nombres coincidentes.

QML proporciona varios tipos de modelos de datos entre el conjunto incorporado de tipos QML. Además, los modelos pueden crearse con Qt C++ y luego ponerse a disposición de QQmlEngine para que los utilicen los componentes QML. Para obtener información sobre la creación de estos modelos, visite los artículos Uso de modelos C++ con Qt Quick Views y Creación de tipos QML.

El posicionamiento de los elementos de un modelo puede lograrse utilizando un Repeater.

Modelo de lista

ListModel es una jerarquía simple de tipos especificados en QML. Las funciones disponibles se especifican mediante las propiedades ListElement.

ListModel {
    id: fruitModel

    ListElement {
        name: "Apple"
        cost: 2.45
    }
    ListElement {
        name: "Orange"
        cost: 3.25
    }
    ListElement {
        name: "Banana"
        cost: 1.95
    }
}

El modelo anterior tiene dos roles, nombre y coste. Estos pueden ser vinculados por un delegado ListView, por ejemplo:

ListView {
    anchors.fill: parent
    model: fruitModel
    delegate: Row {
        id: delegate
        required property string name
        required property real cost

        Text { text: "Fruit: " + delegate.name }
        Text { text: "Cost: $" + delegate.cost }
    }
}

ListModel proporciona métodos para manipular el ListModel directamente a través de JavaScript. En este caso, el primer elemento insertado determina los roles disponibles para cualquier vista que utilice el modelo. Por ejemplo, si se crea un ListModel vacío y se rellena mediante JavaScript, los roles proporcionados por la primera inserción son los únicos roles que se mostrarán en la vista:

ListModel { id: fruitModel }
    ...
MouseArea {
    anchors.fill: parent
    onClicked: fruitModel.append({"cost": 5.95, "name":"Pizza"})
}

Cuando se haga clic en MouseArea, fruitModel tendrá dos roles, coste y nombre. Incluso si se añaden roles posteriores, sólo los dos primeros serán manejados por las vistas que utilicen el modelo. Para restablecer los roles disponibles en el modelo, llame a ListModel::clear().

Modelo XML

XmlListModel permite construir un modelo a partir de una fuente de datos XML. Los roles se especifican a través del tipo XmlListModelRole. Es necesario importar el tipo.

import QtQml.XmlListModel

El siguiente modelo tiene tres roles, title, link y pubDate:

XmlListModel {
     id: feedModel
     source: "http://rss.news.yahoo.com/rss/oceania"
     query: "/rss/channel/item"
     XmlListModelRole { name: "title"; elementName: "title" }
     XmlListModelRole { name: "link"; elementName: "link" }
     XmlListModelRole { name: "pubDate"; elementName: "pubDate" }
}

La propiedad query especifica que el XmlListModel genera un elemento del modelo para cada <item> en el documento XML.

La demostración de noticias RSS muestra cómo puede utilizarse XmlListModel para mostrar un canal RSS.

Modelo de objeto

ObjectModel contiene los elementos visuales que se utilizarán en una vista. Cuando se utiliza un ObjectModel en una vista, ésta no necesita un delegado porque el ObjectModel ya contiene el delegado visual (elementos).

El ejemplo siguiente coloca tres rectángulos de colores en un ListView.

import QtQuick 2.0
import QtQml.Models 2.1

Rectangle {
    ObjectModel {
        id: itemModel
        Rectangle { height: 30; width: 80; color: "red" }
        Rectangle { height: 30; width: 80; color: "green" }
        Rectangle { height: 30; width: 80; color: "blue" }
    }

    ListView {
        anchors.fill: parent
        model: itemModel
    }
}

Enteros como modelos

Un número entero puede utilizarse como un modelo que contiene un cierto número de tipos. En este caso, el modelo no tiene ninguna función de datos.

El siguiente ejemplo crea un ListView con cinco elementos:

Item {
    width: 200; height: 250

    Component {
        id: itemDelegate

        Text {
            required property int index
            text: "I am item number: " + index
        }
    }

    ListView {
        anchors.fill: parent
        model: 5
        delegate: itemDelegate
    }

}

Nota: El límite del número de elementos en un modelo entero es 100.000.000.

Instancias de objetos como modelos

Una instancia de objeto puede utilizarse para especificar un modelo con un único tipo de objeto. Las propiedades del objeto se proporcionan como roles.

El siguiente ejemplo crea una lista con un elemento, mostrando el color del texto miTexto. Nótese el uso de la propiedad model.color completamente cualificada para evitar chocar con la propiedad color del tipo Text en el delegado.

Rectangle {
    width: 200; height: 250

    Text {
        id: myText
        text: "Hello"
        color: "#dd44ee"
    }

    Component {
        id: myDelegate

        Text {
            required property var model
            text: model.color
        }
    }

    ListView {
        anchors.fill: parent
        anchors.topMargin: 30
        model: myText
        delegate: myDelegate
    }
}

Modelos de datos C

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

Para obtener más información, visite el artículo Uso de modelos C++ con vistas Qt Quick .

Modelos de matrices

Puede utilizar matrices JavaScript y varios tipos de listas QML como modelos. Los elementos de la lista estarán disponibles como model y modelData según las reglas descritas anteriormente: Los datos singulares, como números enteros o cadenas, están disponibles como modelData singular. Los datos estructurados, como objetos JavaScript o QObjects, están disponibles como modelData y modelData estructurados.

Los roles individuales del modelo también están disponibles si se solicitan como propiedades requeridas. Dado que no podemos saber de antemano qué objetos aparecerán en un array, cualquier propiedad requerida en un delegado se rellenará, posiblemente con una coerción de undefined al tipo requerido. Sin embargo, las funciones individuales del modelo no están disponibles a través del contexto QML. Serían la sombra de todas las demás propiedades del contexto.

Repetidores

Los repetidores crean elementos a partir de una plantilla para su uso con posicionadores, utilizando datos de un modelo. Combinar repetidores y posicionadores es una forma sencilla de disponer muchos elementos. Un elemento Repeater se coloca dentro de un posicionador, y genera elementos que el posicionador que lo encierra ordena.

Cada repetidor crea un número de elementos combinando cada elemento de datos de un modelo, especificado mediante la propiedad model, con el elemento del modelo, definido como elemento hijo dentro del repetidor. El número total de elementos viene determinado por la cantidad de datos del modelo.

El siguiente ejemplo muestra un repetidor utilizado con un elemento Grid para organizar un conjunto de elementos Rectangle. El elemento Repetidor crea una serie de 24 rectángulos para que el elemento Cuadrícula los coloque en una disposición de 5 por 5.

import QtQuick

Rectangle {
    width: 400
    height: 400
    color: "black"

    Grid {
        x: 5
        y: 5
        rows: 5
        columns: 5
        spacing: 10

        Repeater {
            model: 24
            Rectangle {
                id: delegate

                required property int index

                width: 70
                height: 70
                color: "lightgreen"

                Text {
                    text: delegate.index
                    font.pointSize: 30
                    anchors.centerIn: parent
                }
            }
        }
    }
}

El número de elementos creados por un Repetidor se mantiene mediante su propiedad count. No es posible establecer esta propiedad para determinar el número de elementos a crear. En su lugar, como en el ejemplo anterior, utilizamos un número entero como modelo.

Para más detalles, consulte el documento Modelos de datos QML.

Si el modelo es una lista de cadenas, el delegado también está expuesto a la propiedad habitual de sólo lectura modelData que contiene la cadena. Por ejemplo:

Column {
    Repeater {
        model: ["apples", "oranges", "pears"]
        Text {
            required property string modelData
            text: "Data: " + modelData
        }
    }
}

También es posible utilizar un delegado como modelo para los elementos creados por un Repetidor. Esto se especifica utilizando la propiedad delegate.

Modificación de los datos del modelo

Todas las vistas relevantes tienen una propiedad llamada delegateModelAccess que gobierna si y cómo puedes cambiar los datos del modelo desde el delegado. Para la mayoría de los casos de uso, debe establecerla en DelegateModel.ReadWrite. De este modo, el delegado podrá modificar los datos del modelo de la forma más flexible. Alternativamente, puedes establecerlo en DelegateModel.ReadOnly si no quieres que el delegado cambie ningún dato del modelo.

La siguiente tabla describe en detalle todos los valores que puede tener la propiedad.

DelegateModel.Qt5ReadWriteEl delegado puede asignar valores a cualquier propiedad de contexto proporcionada por la vista para cambiar el elemento del modelo correspondiente. Además, también puede asignar valores a propiedades del objeto model proporcionadas como propiedad de contexto o propiedad requerida para el mismo efecto. Sin embargo, el delegado no puede cambiar los datos del modelo asignando valores a las propiedades requeridas rellenadas por la vista. Si asignas un valor a una propiedad obligatoria de un delegado, se rompe el enlace que actualiza la propiedad obligatoria a partir de los datos del modelo. Esto hace que la propiedad requerida mantenga el valor que le has asignado incluso si el modelo cambia más tarde. DelegateModel.Qt5ReadWrite es el valor por defecto de delegateModelAccess.
DelegateModel.ReadOnlyEl delegado no puede asignar valores a propiedades de contexto proporcionadas por la vista, ni puede asignar valores a propiedades del objeto model. Asignar un valor a una propiedad requerida rellenada por la vista no rompe el enlace interno, ni cambiará ningún dato del modelo. La propiedad requerida mantendrá el valor asignado hasta que el elemento del modelo vuelva a cambiar.
DelegateModelLectura y escrituraEl delegado puede asignar valores a cualquier propiedad de contexto proporcionada por la vista para cambiar el elemento del modelo correspondiente. Además, también puede asignar valores a propiedades del objeto model proporcionadas como propiedad de contexto o propiedad requerida con el mismo efecto. El delegado también puede cambiar los datos del modelo asignando valores a las propiedades requeridas rellenadas por la vista. Al asignar un valor a una propiedad obligatoria, el valor se propagará al elemento del modelo correspondiente y no se romperán los enlaces internos.

Algunos modelos son objetos con identidades independientes a los que la vista hace referencia. El objeto original es la única fuente de verdad para crear delegados. No se copia. Tales modelos se actualizarán visiblemente al escribir a través de delegados.

Otros modelos no tienen una identidad independiente y se copian al asignarlos a la vista. Para estos modelos, sólo se actualizan los elementos internos de la vista cuando se escribe a través del delegado. El modelo original permanece inalterado.

En general, los tipos de objeto QML tienen identidades independientes, mientras que los tipos de valor QML no. Por lo tanto, ListModel, cualquier cosa derivada de QAbstractItemModel, así como una única instancia de un tipo de objeto o una lista de instancias de tipos de objeto se actualizarán cuando se pasen como modelo y se escriban a través del delegado. Sin embargo, las matrices de JavaScript, las listas de tipos de valor o los números simples no reciben actualizaciones cuando se cambian los datos del modelo a través del delegado.

Además, al implementar tu propio modelo C++, necesitas implementar setData para recibir cualquier actualización pasada desde los delegados.

Supongamos que un modelo C++ basado en QAbstractItemModel que implemente el método setData se registra como un tipo QML denominado EditableModel. Los datos podrían escribirse en el modelo de la siguiente manera:

ListView {
    anchors.fill: parent
    model: EditableModel {}

    // Make sure that changes to the required property are propagated
    delegateModelAccess: DelegateModel.ReadWrite

    delegate: TextEdit {
        required property string edit

        width: ListView.view.width
        height: 30
        text: edit
        Keys.onReturnPressed: edit = text
    }
}

También se pueden cambiar los datos del modelo manipulando el objeto model de esta manera:

ListView {
    anchors.fill: parent
    model: EditableModel {}
    delegate: TextEdit {
        required property QtObject model

        width: ListView.view.width
        height: 30
        text: model.edit
        Keys.onReturnPressed: model.edit = text
    }
}

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

Para obtener más información, visite el artículo Uso de modelos C++ con vistas Qt Quick .

Uso de transiciones

Las transiciones pueden utilizarse para animar elementos que se añaden, mueven o eliminan de un posicionador.

Las transiciones para añadir elementos se aplican a los elementos que se crean como parte de un posicionador, así como a los que se reasignan para convertirse en hijos de un posicionador.

Las transiciones para eliminar elementos se aplican a los elementos que se eliminan dentro de un posicionador, así como a los que se eliminan de un posicionador y se les asignan nuevos padres en un documento.

Nota: Cambiar la opacidad de los elementos a cero no hará que desaparezcan del posicionador. Se pueden eliminar y volver a añadir cambiando la propiedad visible.

© 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.