Estructura de un documento QML
Un documento QML es una pieza autónoma de código fuente QML que consta de tres partes:
- Una lista opcional de pragmas
- Sus declaraciones de importación
- Una única declaración de objeto raíz
Por convención, una única línea vacía separa las importaciones de la definición de la jerarquía de objetos.
Los documentos QML se codifican siempre en formato UTF-8.
Pragmas
Los pragmas son instrucciones para el propio motor QML que pueden utilizarse para especificar determinadas características de los objetos del archivo actual o para modificar el modo en que el motor interpreta el código. A continuación se explican en detalle los siguientes pragmas.
| pragma | valores | valor por defecto | desde |
|---|---|---|---|
| Singleton | 5.2 | ||
| ListPropertyAssignBehavior | Añadir | X | 6.3 |
| Sustituir | 6.3 | ||
| ReplaceIfNotDefault | 6.3 | ||
| ComponentBehavior | Vinculado | 6.4 | |
| Sin consolidar | X | 6.4 | |
| FunctionSignatureBehavior | Ignorado | 6.5 | |
| Forzado | X | 6.5 | |
| NativeMethodBehavior | AcceptThisObject | 6.5 | |
| RejectThisObject | X | 6.5 | |
| ValueTypeBehavior | Referencia | X | 6.5 |
| Copiar | 6.5 | ||
| Direccionable | 6.6 | ||
| Direccionable | X | 6.6 | |
| Asertable | 6.8 | ||
| Traductor | <contexto de traducción> | <nombre de archivo> | 6.7 |
Singleton
pragma Singleton declara el componente definido en la raíz del documento QML como singleton. Consulte Singletons en QML para obtener más información.
ListPropertyAssignBehavior
Con este pragma puede definir cómo se gestionarán las asignaciones a propiedades de lista en los componentes definidos en el documento QML. Por defecto, la asignación a una propiedad de lista se añade a la lista. Puede solicitar explícitamente este comportamiento utilizando el valor Append. Como alternativa, puede solicitar que el contenido de las propiedades de lista se sustituya siempre mediante Replace, o que se sustituya si la propiedad no es la predeterminada mediante ReplaceIfNotDefault.
Considere un tipo base en un documento Base.qml:
pragma ListPropertyAssignBehavior: ReplaceIfNotDefault import QtQuick Item { objectName: "outer" default property list<Item> d: [ Item { objectName: "inner" } ] property list<Item> notDefault: [ Item { objectName: "one" } ] }
Entonces, si usted deriva de Base y modifica sus propiedades de lista, el ListPropertyAssignBehavior tiene efecto. En este caso:
Base { // The new item is appended to the list even though you're assigning. // The (default) property "d" now contains "inner" and "inner2". d: [ Item { objectName: "inner2" } ] // The list is replaced by the list given here. // The (non-default) property "notDefault" now contains only "two". notDefault: [ Item { objectName: "two" } ] }
Si no se indica ListPropertyAssignBehavior o si se indica Append, el objeto "dos" se añadirá a la propiedad notDefault, dando como resultado una lista que contiene "uno" y "dos".
Si se indica Replace, el contenido de la propiedad por defecto "d" también será reemplazado, dando como resultado una lista que contiene sólo "inner2".
Nota: La misma declaración puede darse también para tipos definidos en C++, añadiendo las macros QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND, QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE, y QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT a la declaración de la clase. Por ejemplo:
class MyType : public QObject { Q_OBJECT QML_ELEMENT QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE Q_PROPERTY(QQmlListProperty<QObject> a READ a) [...] };
ComponentBehavior
Puede tener varios componentes definidos en el mismo archivo QML. El ámbito raíz del archivo QML es un componente, y además puede tener elementos de tipo QQmlComponent, creados explícita o implícitamente como propiedades, o componentes en línea. Estos componentes están anidados. Cada uno de los componentes interiores está dentro de un componente exterior específico. La mayoría de las veces, los ID definidos en un componente externo son accesibles dentro de todos sus componentes internos anidados. Sin embargo, puede crear elementos a partir de un componente en cualquier contexto diferente, con diferentes ID disponibles. Al hacerlo, se rompe la suposición de que los ID externos están disponibles. Por lo tanto, el motor y las herramientas QML no pueden saber de antemano a qué tipo, si lo hay, se resolverán dichos ID en tiempo de ejecución.
Con el pragma ComponentBehavior puede restringir todos los componentes internos definidos en un archivo para que sólo creen objetos dentro de su contexto original. Si un componente está vinculado a su contexto, puede utilizar con seguridad ID de componentes externos en el mismo archivo dentro del componente. Las herramientas QML asumirán entonces que los ID externos con sus tipos específicos están disponibles.
Para vincular los componentes a su contexto, especifique el argumento Bound:
pragma ComponentBehavior: Bound
Esto implica que, en caso de conflicto de nombres, los ID definidos fuera de un componente vinculado anulan las propiedades locales de los objetos creados a partir del componente. De lo contrario, no sería seguro utilizar los ID, ya que versiones posteriores de un módulo podrían añadir más propiedades al componente. Si el componente no está enlazado, las propiedades locales anulan los IDs definidos fuera del componente, pero no los IDs definidos dentro del componente.
El ejemplo siguiente imprime la propiedad r del objeto ListView con el id color, no la propiedad r del color del rectángulo.
pragma ComponentBehavior: Bound import QtQuick ListView { id: color property int r: 12 model: 1 delegate: Rectangle { Component.onCompleted: console.log(color.r) } }
El valor por defecto de ComponentBehavior es Unbound. También puede especificarlo explícitamente. En una futura versión de Qt el valor por defecto cambiará a Bound.
Los componentes delegados vinculados a su contexto no reciben sus propios contextos privados en la instanciación. Esto significa que los datos del modelo sólo pueden pasarse a través de propiedades requeridas en este caso. La transmisión de datos del modelo a través de propiedades de contexto no funcionará. Esto afecta a los delegados de, por ejemplo, Instantiator, Repeater, ListView, TableView, GridView, TreeView y, en general, cualquier cosa que utilice DelegateModel internamente.
Por ejemplo, lo siguiente no funcionará:
pragma ComponentBehavior: Bound import QtQuick ListView { delegate: Rectangle { color: model.myColor } }
La propiedad delegate de ListView es un componente. Por lo tanto, aquí se crea implícitamente un Component alrededor del Rectangle. Ese componente está ligado a su contexto. No recibe la propiedad de contexto model proporcionada por ListView. Para que funcione, tendrías que escribirlo de esta manera:
pragma ComponentBehavior: Bound import QtQuick ListView { delegate: Rectangle { required property color myColor color: myColor } }
Puedes anidar componentes en un archivo QML. El pragma se aplica a todos los componentes del archivo, independientemente de la profundidad de anidamiento.
FunctionSignatureBehavior
Con este pragma puedes cambiar la forma en que se manejan las anotaciones de tipo en las funciones. Desde Qt 6.7 las anotaciones de tipo se aplican al llamar a funciones. Antes, sólo el compilador de scripts QML aplicaba las anotaciones de tipo. El intérprete y el compilador JIT las ignoraban. Aplicar siempre las anotaciones de tipo es un cambio de comportamiento en comparación con versiones anteriores, ya que antes se podían llamar funciones con argumentos no coincidentes.
Especificar Ignored como valor hace que el motor QML y el compilador de scripts QML ignoren cualquier anotación de tipo y, por tanto, restaura el comportamiento anterior a la versión 6.7 del intérprete y el JIT. Como resultado, se compila menos código a C++ de antemano y hay que interpretar o compilar más código en el JIT.
Especificar Enforced como valor establece explícitamente el valor por defecto: Las anotaciones de tipo se aplican siempre.
NativeMethodBehavior
La llamada a métodos C++ con objetos this diferentes de aquellos de los que fueron recuperados está rota, debido a razones históricas. El objeto original se utiliza como objeto this. Puede permitir que se utilice el objeto this especificando pragma NativeMethodBehavior: AcceptThisObject. Especificando RejectThisObject se mantiene el comportamiento histórico.
Un ejemplo de esto se puede encontrar en Métodos C++ y el objeto 'this'.
Comportamiento de ValueType
Con este pragma puede cambiar la forma en que se manejan los tipos de valor y las secuencias.
Normalmente los nombres en minúsculas no pueden ser nombres de tipo en código JavaScript. Esto es un problema porque los nombres de tipos de valor están en minúsculas. Puede especificar Addressable como valor para este pragma para cambiar esto. Si se especifica Addressable, un valor JavaScript puede ser explícitamente coaccionado a un tipo de valor específico y nombrado. Esto se hace utilizando el operador as, como se haría con los tipos de objeto. Además, también puede comprobar los tipos de valor utilizando el operador instanceof:
pragma ValueTypeBehavior: Addressable import QtQml QtObject { property var a property real b: (a as rect).x property bool c: a instanceof rect property var rect // inaccessible. "rect" is a type name. }
Dado que rect en el ejemplo anterior es ahora un nombre de tipo, hará sombra a cualquier propiedad llamada rect.
La conversión explícita al tipo deseado ayuda a las herramientas. Puede permitir que el compiladorQt Quick genere código eficiente donde de otro modo no podría. Puede utilizar qmllint para encontrar tales ocurrencias.
También hay un valor Inaddressable que puede utilizar para especificar explícitamente el comportamiento predeterminado.
Otro atributo del pragma ValueTypeBehavior es Assertable, introducido en Qt 6.8. Debido a un error en Qt 6.6 y 6.7 el a as rect anterior no sólo comprueba si a es un rect sino que también construye un rect si a es de un tipo compatible. Obviamente esto no es lo que una aserción de tipo debería hacer. Especificar Assertable previene este comportamiento y restringe las aserciones de tipo para tipos de valor para que sólo comprueben el tipo. Debería especificarlo siempre si va a utilizar tipos de valor con as. En cualquier caso, si la aserción de tipo para un tipo de valor falla, el resultado es undefined.
instanceof no tiene este problema ya que sólo comprueba la herencia, no todas las posibles coerciones de tipo.
Nota: Utilizar as con los tipos int y double no es aconsejable ya que según las reglas de JavaScript, el resultado de cualquier cálculo es un número en coma flotante, incluso si resulta tener el mismo valor que su equivalente entero. A la inversa, cualquier constante entera que declare en JavaScript no es un double según las reglas de asignación de tipos de QML. Además, int y double son palabras reservadas. Estos tipos sólo se pueden utilizar mediante espacios de nombres de tipos.
Los tipos de valor y las secuencias se tratan generalmente como referencias. Esto significa que, si recupera una instancia de tipo de valor de una propiedad en un valor local y, a continuación, modifica el valor local, la propiedad original también se modifica. Además, si escribe la propiedad original explícitamente, el valor local también se actualiza. Este comportamiento es poco intuitivo en muchos lugares, y no deberías confiar en él. Los valores Copy y Reference del pragma ValueTypeBehavior son opciones experimentales para cambiar este comportamiento. No debe utilizarlas. Especificar Copy hace que todos los tipos de valores se traten como copias reales. Especificar Reference establece explícitamente el comportamiento por defecto.
En lugar de utilizar Copy debe recargar explícitamente las referencias a los tipos de valores y secuencias cada vez que puedan haber sido afectados por efectos secundarios. Los efectos secundarios pueden producirse siempre que se llame a una función o se establezca imperativamente una propiedad. qmllint proporciona orientación al respecto. Por ejemplo, en el siguiente código la variable f se ve afectada por efectos secundarios después de escribir width. Esto se debe a que puede haber un enlace en un tipo derivado o en un elemento Binding que actualiza font cuando se cambia width.
import QtQuick Text { function a() : real { var f = font; width = f.pixelSize; return f.pointSize; } }
Para solucionar esto, se puede evitar mantener f durante la operación de escritura en width:
import QtQuick Text { function a() : real { var f = font; width = f.pixelSize; f = font; return f.pointSize; } }
Esto, a su vez, puede abreviarse:
import QtQuick Text { function a() : real { width = font.pixelSize; return font.pointSize; } }
Podrías suponer que volver a recuperar la propiedad font es costoso, pero en realidad el motor QML refresca automáticamente las referencias de tipo valor cada vez que lees de ellas. Así que esto no es más costoso que la primera versión, sino una forma más clara de expresar las mismas operaciones.
Traductor
Con este pragma puedes establecer el contexto para las traducciones en el fichero.
pragma Translator: myTranslationContext
pragma Translator: "myTranslationContext"
Para más información sobre internacionalización con QML, vea Escribiendo código fuente para traducción en QML.
Importación
Un documento debe importar los módulos o espacios de nombres de tipos necesarios para que el motor pueda cargar los tipos de objetos QML a los que se hace referencia en el documento. Por defecto, un documento puede acceder a cualquier tipo de objeto QML que se haya definido a través de los archivos .qml en el mismo directorio; si un documento necesita hacer referencia a cualquier otro tipo de objeto, debe importar el espacio de nombres de tipos en el que se hayan registrado dichos tipos.
QML no dispone de un preprocesador que modifique el documento antes de presentarlo a QML engine, a diferencia de C o C++. Las sentencias import no copian y anteponen el código del documento, sino que indican al motor QML cómo resolver las referencias de tipo que se encuentran en el documento. Cualquier referencia de tipo presente en un documento QML -como Rectangle y ListView -, incluidas las realizadas dentro de un bloque JavaScript o los enlaces de propiedades, se resuelven basándose exclusivamente en las sentencias import. Debe haber al menos una sentencia import, como import QtQuick 2.0.
Consulte la documentación Sintaxis QML - Declaraciones de importación para obtener información detallada sobre las importaciones QML.
La declaración de objeto raíz
Un documento QML describe una jerarquía de objetos que pueden instanciarse. Cada definición de objeto tiene una estructura determinada; tiene un tipo, puede tener un id y un nombre de objeto, puede tener propiedades, puede tener métodos, puede tener señales y puede tener manejadores de señales.
Un archivo QML sólo debe contener una única definición de objeto raíz. Lo siguiente no es válido y generará un error:
// MyQmlFile.qml
import QtQuick 2.0
Rectangle { width: 200; height: 200; color: "red" }
Rectangle { width: 200; height: 200; color: "blue" } // invalid!Esto se debe a que un archivo .qml define automáticamente un tipo QML, que encapsula una única definición de objeto QML. Esto se trata con más detalle en Documentos como definiciones de tipo de objeto QML.
Véase también Anotaciones y aserciones de tipo.
© 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.