Atributos de los objetos QML
Cada tipo de objeto QML tiene un conjunto definido de atributos. Cada instancia de un tipo de objeto se crea con el conjunto de atributos que se han definido para ese tipo de objeto. Se pueden especificar varios tipos de atributos, que se describen a continuación.
Atributos en las declaraciones de objetos
Una declaración de objeto en un documento QML define un nuevo tipo. También declara una jerarquía de objetos que se instanciará si se crea una instancia de ese tipo recién definido.
El conjunto de tipos de atributos de tipo de objeto QML es el siguiente:
- el atributo id
- atributos de propiedad
- atributos de señal
- atributos de manejador de señal
- atributos de método
- propiedades adjuntas y atributos de manejador de señal adjuntos
- atributos de enumeración
Estos atributos se tratan en detalle a continuación.
Atributo id
Un elemento QML puede tener como máximo un atributo id. Este atributo lo proporciona el propio lenguaje y no puede ser redefinido ni sobrescrito por ningún tipo de objeto QML.
Se puede asignar un valor al atributo id de una instancia de objeto para que otros objetos puedan identificarlo y hacer referencia a él. Este id debe comenzar por una letra minúscula o un guión bajo, y no puede contener caracteres distintos de letras, números y guiones bajos. Tampoco puede ser una palabra clave de JavaScript. Consulte la Especificación del lenguaje ECMAScript para obtener una lista de dichas palabras clave.
Si utiliza un nombre no apto como identificador de JavaScript en QML, como as, no podrá hacer referencia al objeto identificado en JavaScript, lo que hace que el id sea prácticamente inútil. No obstante, puede utilizar QQmlContext desde C++ para interactuar con dichos identificadores.
A continuación se muestra un objeto TextInput y un objeto Text. El valor id del objeto TextInput se establece en "myTextInput". El objeto Text establece su propiedad text para que tenga el mismo valor que la propiedad text del objeto TextInput, haciendo referencia a myTextInput.text. Ahora, ambos objetos mostrarán el mismo texto:
import QtQuick Column { width: 200; height: 200 TextInput { id: myTextInput; text: "Hello World" } Text { text: myTextInput.text } }
Se puede hacer referencia a un objeto por su id desde cualquier lugar dentro del contexto QML en el que se crea. Por lo tanto, un valor id debe ser siempre único dentro de su contexto. Para más información, véase Ámbito y resolución de nombres.
El contexto también se expone a C++ a través de la jerarquía QQmlContext. Puede, por ejemplo, recuperar el contexto de un objeto específico a través de la función qmlContext y preguntar por otros objetos en el mismo contexto:
QObject *textInput = qmlContext(theColumn)->objectForName("myTextInput");
Una vez creada una instancia de objeto, el valor de su atributo id no puede modificarse. Aunque pueda parecer una propiedad ordinaria, el atributo id no es un atributo ordinario de property, y se le aplica una semántica especial; por ejemplo, no es posible acceder a myTextInput.id en el ejemplo anterior.
Atributos de propiedad
Una propiedad es un atributo de un objeto al que se puede asignar un valor estático o vincularlo a una expresión dinámica. El valor de una propiedad puede ser leído por otros objetos. Por lo general, también puede ser modificado por otro objeto, a menos que un tipo QML concreto lo haya prohibido explícitamente para una propiedad específica.
Definición de atributos de propiedad
Una propiedad puede definirse para un tipo en C++ registrando un Q_PROPERTY de una clase que, a su vez, se registra en el sistema de tipos QML. Alternativamente, una propiedad personalizada de un tipo de objeto puede definirse en una declaración de objeto en un documento QML con la siguiente sintaxis:
[default] [virtual] [override] [final] [required] [readonly] property <propertyType> <propertyName>
De esta forma una declaración de objeto puede exponer un valor particular a objetos externos o mantener algún estado interno más fácilmente.
Los nombres de propiedad deben empezar por una letra minúscula y sólo pueden contener letras, números y guiones bajos. Las palabras reservadas de JavaScript no son nombres de propiedad válidos. Las palabras clave default, required, readonly, virtual, override, final son opcionales y modifican la semántica de la propiedad declarada. Consulte las próximas secciones sobre propiedades predeterminadas, propiedades obligatorias, propiedades de sólo lectura y semántica de anulación para obtener más información sobre sus respectivos significados.
Declarar una propiedad personalizada crea implícitamente una señal de cambio de valor para esa propiedad, así como un manejador de señal asociado llamado on<NombreDeLaPropiedad>Changed, donde <NombreDeLaPropiedad> es el nombre de la propiedad, con la primera letra en mayúscula.
Por ejemplo, la siguiente declaración de objeto define un nuevo tipo que deriva del tipo base Rectángulo. Tiene dos nuevas propiedades, con un manejador de señal implementado para una de esas nuevas propiedades:
Rectangle { property color previousColor property color nextColor onNextColorChanged: console.log("The next color will be: " + nextColor.toString()) }
Tipos válidos en definiciones de propiedades personalizadas
Cualquiera de los tipos de valor QML puede utilizarse como tipo de propiedad personalizada. Por ejemplo, todas estas son declaraciones de propiedades válidas:
(Los valores de enumeración son simplemente valores numéricos enteros y se puede hacer referencia a ellos con el tipo int en su lugar).
Algunos tipos de valor son proporcionados por el módulo QtQuick y, por tanto, no pueden utilizarse como tipos de propiedad a menos que se importe el módulo. Consulte la documentación sobre tipos de valor QML para obtener más información.
Tenga en cuenta que el tipo de valor var es un tipo de marcador de posición genérico que puede contener cualquier tipo de valor, incluidas listas y objetos:
property var someNumber: 1.5 property var someString: "abc" property var someBool: true property var someList: [1, 2, "three", "four"] property var someObject: Rectangle { width: 100; height: 100; color: "red" }
Además, cualquier tipo de objeto QML puede utilizarse como tipo de propiedad. Por ejemplo:
property Item someItem property Rectangle someRectangle
Esto también se aplica a los tipos QML personalizados. Si se definiera un tipo QML en un archivo denominado ColorfulButton.qml (en un directorio que luego importara el cliente), también sería válida una propiedad del tipo ColorfulButton.
Asignación de valores a atributos de propiedades
El valor de una propiedad de una instancia de objeto puede especificarse de dos formas distintas:
- una asignación de valor en la inicialización
- una asignación de valor imperativa
En ambos casos, el valor puede ser un valor estático o un valor de expresión vinculante.
Asignación de valor en la inicialización
La sintaxis para asignar un valor a una propiedad en la inicialización es:
<propertyName> : <value>
Una asignación de valor en la inicialización puede combinarse con una definición de propiedad en una declaración de objeto, si se desea. En ese caso, la sintaxis de la definición de propiedad pasa a ser:
[default] property <propertyType> <propertyName> : <value>
A continuación se muestra un ejemplo de inicialización del valor de una propiedad:
import QtQuick Rectangle { color: "red" property color nextColor: "blue" // combined property declaration and initialization }
Asignación imperativa de valor
Una asignación de valor imperativa es aquella en la que un valor de propiedad (ya sea un valor estático o una expresión vinculante) se asigna a una propiedad desde código JavaScript imperativo. La sintaxis de una asignación de valor imperativa es simplemente el operador de asignación de JavaScript, como se muestra a continuación:
[<objectId>.]<propertyName> = value
A continuación se muestra un ejemplo de asignación imperativa de valores:
import QtQuick Rectangle { id: rect Component.onCompleted: { rect.color = "red" } }
Valores estáticos y valores de expresión vinculante
Como se ha indicado anteriormente, existen dos tipos de valores que pueden asignarse a una propiedad: valores estáticos y valores de expresión vinculante. Estos últimos también se conocen como propiedades vinculadas.
| Tipo | Semántica |
|---|---|
| Valor estático | Valor constante que no depende de otras propiedades. |
| Expresión de enlace | Expresión de JavaScript que describe la relación de una propiedad con otras propiedades. Las variables de esta expresión se denominan dependencias de la propiedad. El motor QML refuerza la relación entre una propiedad y sus dependencias. Cuando alguna de las dependencias cambia de valor, el motor QML reevalúa automáticamente la expresión de vinculación y asigna el nuevo resultado a la propiedad. |
A continuación se muestra un ejemplo que muestra ambos tipos de valores asignados a propiedades:
import QtQuick Rectangle { // both of these are static value assignments on initialization width: 400 height: 200 Rectangle { // both of these are binding expression value assignments on initialization width: parent.width / 2 height: parent.height } }
Nota: Para asignar una expresión de vinculación imperativamente, la expresión de vinculación debe estar contenida en una función que se pasa a Qt.binding(), y luego el valor devuelto por Qt.binding() debe asignarse a la propiedad. Por el contrario, Qt.binding() no debe utilizarse cuando se asigna una expresión de vinculación en la inicialización. Véase Property Binding para más información.
Seguridad de tipos
Las propiedades son de tipo seguro. A una propiedad sólo se le puede asignar un valor que coincida con el tipo de propiedad.
Por ejemplo, si una propiedad es un int, y si intenta asignarle una cadena, obtendrá un error:
property int volume: "four" // generates an error; the property's object will not be loaded
Del mismo modo, si a una propiedad se le asigna un valor de tipo incorrecto durante el tiempo de ejecución, no se asignará el nuevo valor y se generará un error.
Algunos tipos de propiedades no tienen una representación de valor natural, y para esos tipos de propiedades el motor QML realiza automáticamente la conversión de cadena a valor tipado. Así, por ejemplo, aunque las propiedades del tipo color almacenan colores y no cadenas, puede asignar la cadena "red" a una propiedad de color sin que se produzca ningún error.
Consulte Tipos de valor QML para obtener una lista de los tipos de propiedades que se admiten de forma predeterminada. Además, cualquier tipo de objeto QML disponible también puede utilizarse como tipo de propiedad.
Tipos de propiedad especiales
Atributos de propiedad de lista de objetos
A una propiedad de tipo list se le puede asignar una lista de valores de tipo objeto QML. La sintaxis para definir un valor de lista de objetos es una lista separada por comas y rodeada de corchetes:
[ <item 1>, <item 2>, ... ]
Por ejemplo, el tipo Item tiene una propiedad states que se utiliza para contener una lista de objetos de tipo State. El código siguiente inicializa el valor de esta propiedad a una lista de tres objetos State:
import QtQuick Item { states: [ State { name: "loading" }, State { name: "running" }, State { name: "stopped" } ] }
Si la lista contiene un único elemento, pueden omitirse los corchetes:
Una propiedad de tipo list puede especificarse en una declaración de objeto con la siguiente sintaxis:
[default] property list<<ObjectType>> propertyName
y, al igual que otras declaraciones de propiedades, se puede combinar una inicialización de propiedad con la declaración de propiedad con la siguiente sintaxis:
[default] property list<<ObjectType>> propertyName: <value>
A continuación se muestra un ejemplo de declaración de propiedad de lista:
import QtQuick Rectangle { // declaration without initialization property list<Rectangle> siblingRects // declaration with initialization property list<Rectangle> childRects: [ Rectangle { color: "red" }, Rectangle { color: "blue"} ] }
Si desea declarar una propiedad para almacenar una lista de valores que no son necesariamente valores de tipo objeto QML, debe declarar en su lugar una propiedad var.
Propiedades agrupadas
En algunos casos, las propiedades contienen un grupo lógico de atributos de subpropiedad. Estos atributos de subpropiedad se pueden asignar utilizando la notación de puntos o la notación de grupo.
Por ejemplo, el tipo Text tiene una propiedad de grupo font. A continuación, el primer objeto Text inicializa sus valores font utilizando la notación de puntos, mientras que el segundo utiliza la notación de grupo:
Text {
//dot notation
font.pixelSize: 12
font.b: true
}
Text {
//group notation
font { pixelSize: 12; b: true }
}Los tipos de propiedades agrupadas son tipos que tienen subpropiedades. Si un tipo de propiedad agrupada es un tipo objeto (en contraposición a un tipo valor), la propiedad que la contiene debe ser de sólo lectura. Esto es para evitar que reemplace el objeto al que pertenecen las subpropiedades.
Alias de propiedades
Los alias de propiedad son propiedades que contienen una referencia a otra propiedad. A diferencia de una definición de propiedad ordinaria, que asigna un nuevo y único espacio de almacenamiento para la propiedad, un alias de propiedad conecta la nueva propiedad declarada (llamada propiedad alias) como una referencia directa a una propiedad existente (la propiedad alias).
Una declaración de alias de propiedad se parece a una definición de propiedad ordinaria, excepto en que requiere la palabra clave alias en lugar de un tipo de propiedad, y el lado derecho de la declaración de propiedad debe ser una referencia de alias válida:
[default] property alias <name>: <alias reference>
A diferencia de una propiedad ordinaria, un alias tiene las siguientes restricciones:
- Sólo puede referirse a un objeto, o a la propiedad de un objeto, que esté dentro del ámbito del tipo dentro del cual se declara el alias.
- No puede contener expresiones JavaScript arbitrarias.
- No puede hacer referencia a objetos declarados fuera del ámbito de su tipo.
- La referencia de alias no es opcional, a diferencia del valor predeterminado opcional de una propiedad ordinaria; la referencia de alias debe proporcionarse cuando se declara el alias por primera vez.
- No puede hacer referencia a propiedades adjuntas.
- No puede referirse a propiedades dentro de una jerarquía con profundidad 3 o superior. El siguiente código no funcionará:
property alias color: myItem.myRect.border.color Item { id: myItem property Rectangle myRect }
Sin embargo, sí funcionarán los alias a propiedades que tengan hasta dos niveles de profundidad.
property alias color: rectangle.border.color Rectangle { id: rectangle }
Por ejemplo, a continuación se muestra un tipo Button con una propiedad alias buttonText que está conectada al objeto text del hijo Text:
// Button.qml import QtQuick Rectangle { property alias buttonText: textItem.text width: 100; height: 30; color: "yellow" Text { id: textItem } }
El siguiente código crearía un Button con una cadena de texto definida para el objeto Text hijo:
Button { buttonText: "Click Me" }
Aquí, modificar buttonText modifica directamente el valor textItem.text; no cambia algún otro valor que luego actualice textItem.text. Si buttonText no fuera un alias, cambiar su valor no cambiaría el texto mostrado, ya que las propiedades no son bidireccionales: el valor de buttonText cambiaría si se cambiara textItem.text, pero no al revés.
Alias de propiedades y tipos
Los alias de propiedad no pueden tener especificaciones de tipo explícitas. El tipo de un alias de propiedad es el tipo declarado de la propiedad u objeto al que hace referencia. Por lo tanto, si creas un alias a un objeto referenciado mediante id con propiedades extra declaradas inline, las propiedades extra no serán accesibles a través del alias:
// MyItem.qml Item { property alias inner: innerItem Item { id: innerItem property int extraProperty } }
No se puede inicializar inner.extraProperty desde fuera de este componente, ya que inner es sólo un Item:
// main.qml MyItem { inner.extraProperty: 5 // fails }
Sin embargo, si extrae el objeto interno en un componente separado con un archivo .qml dedicado, puede instanciar ese componente en su lugar y tener todas sus propiedades disponibles a través del alias:
// MainItem.qml
Item {
// Now you can access inner.extraProperty, as inner is now an ExtraItem
property alias inner: innerItem
ExtraItem {
id: innerItem
}
}
// ExtraItem.qml
Item {
property int extraProperty
}Propiedades por defecto
Una definición de objeto puede tener una única propiedad por defecto. Una propiedad por defecto es la propiedad a la que se asigna un valor si se declara un objeto dentro de la definición de otro objeto sin declararlo como valor de una propiedad concreta.
Declarar una propiedad con la palabra clave opcional default la marca como propiedad por defecto. Por ejemplo, supongamos que existe un archivo MiEtiqueta.qml con una propiedad por defecto someText:
// MyLabel.qml import QtQuick Text { default property var someText text: `Hello, ${someText.text}` }
El valor someText podría asignarse en una definición de objeto MyLabel, de este modo:
MyLabel { Text { text: "world!" } }
Esto tiene exactamente el mismo efecto que lo siguiente:
MyLabel { someText: Text { text: "world!" } }
Sin embargo, dado que la propiedad someText se ha marcado como propiedad por defecto, no es necesario asignar explícitamente el objeto Text a esta propiedad.
Observará que se pueden añadir objetos hijo a cualquier tipo basado en Item sin añadirlos explícitamente a la propiedad children. Esto se debe a que la propiedad por defecto de Item es su propiedad data, y cualquier elemento añadido a esta lista para un Item se añade automáticamente a su lista de children.
Las propiedades por defecto pueden ser útiles para reasignar los hijos de un elemento. Por ejemplo:
Estableciendo el alias de la propiedad por defecto a inner.children, cualquier objeto asignado como hijo del elemento exterior se reasigna automáticamente como hijo del elemento interior.
Atención: El establecimiento de los valores de una propiedad de lista por defecto de un elemento puede hacerse implícita o explícitamente. Dentro de la definición de un mismo elemento, estos dos métodos no deben mezclarse, ya que ello conduce a una ordenación indefinida de los elementos de la lista.
Item { // Use either implicit or explicit assignement to the default list property but not both! Rectangle { width: 40 } // implicit data: [ Rectangle { width: 100 } ] // explicit }
Semántica de la anulación
Por defecto, las propiedades pueden ser anuladas: Se vuelve a declarar una propiedad en un tipo QML derivado, posiblemente con un nuevo tipo y nuevos atributos. El resultado son dos propiedades con el mismo nombre, de las cuales sólo una es accesible en un contexto determinado. Esto rara vez es lo que se desea. A menudo es accidental, y la mayoría de las veces los efectos son bastante confusos. Además, el sombreado es malo para las herramientas.
Para solucionar esto, se introdujeron las palabras clave virtual, override, final y advertencias y errores adicionales.
Para más detalles y un conjunto completo de ejemplos, incluyendo advertencias y errores, consulte la página Property Shadowing and Override Semantics.
Propiedades obligatorias
Una declaración de objeto puede definir una propiedad como requerida, utilizando la palabra clave required. La sintaxis es
required property <propertyType> <propertyName>
Como su nombre indica, las propiedades requeridas deben establecerse cuando se crea una instancia del objeto. La infracción de esta regla provocará que las aplicaciones QML no se inicien si puede detectarse estáticamente. En el caso de componentes QML instanciados dinámicamente (por ejemplo, a través de Qt.createComponent()), la violación de esta regla provoca una advertencia y un valor de retorno nulo.
Es posible hacer obligatoria una propiedad existente con
required <propertyName>
El siguiente ejemplo muestra cómo crear un componente Rectángulo personalizado, en el que siempre es necesario especificar la propiedad color.
// ColorRectangle.qml Rectangle { required color }
Nota: No puede asignar un valor inicial a una propiedad obligatoria desde QML, ya que iría directamente en contra del uso previsto de las propiedades obligatorias.
Las propiedades requeridas juegan un papel especial en el código modelo-vista-delegado: Si el delegado de una vista tiene propiedades obligatorias cuyos nombres coinciden con los nombres de rol del modelo de la vista, dichas propiedades se inicializarán con los valores correspondientes del modelo. Para obtener más información, visita la página Modelos y vistas en Qt Quick.
Consulte QQmlComponent::createWithInitialProperties, QQmlApplicationEngine::setInitialProperties y QQuickView::setInitialProperties para conocer las formas de inicializar propiedades requeridas desde C++.
Propiedades de sólo lectura
Una declaración de objeto puede definir una propiedad de sólo lectura utilizando la palabra clave readonly, con la siguiente sintaxis:
readonly property <propertyType> <propertyName> : <value>
A las propiedades de sólo lectura se les debe asignar un valor estático o una expresión vinculante en la inicialización. Una vez inicializada una propiedad de sólo lectura, ya no se puede cambiar su valor estático o su expresión vinculante.
Por ejemplo, el código del bloque Component.onCompleted que aparece a continuación no es válido:
Item { readonly property int someNumber: 10 Component.onCompleted: someNumber = 20 // TypeError: Cannot assign to read-only property }
Nota: Una propiedad de sólo lectura no puede ser también una propiedad por defecto.
Objetos modificadores de propiedades
Las propiedades pueden tener asociados objetos modificadores del valor de la propiedad. La sintaxis para declarar una instancia de un tipo modificador de propiedad asociado a una propiedad concreta es la siguiente:
<PropertyModifierTypeName> on <propertyName> { // attributes of the object instance }
Esto se conoce comúnmente como sintaxis "on".
Es importante tener en cuenta que la sintaxis anterior es, de hecho, una declaración de objeto que instanciará un objeto que actúa sobre una propiedad preexistente.
Algunos tipos de modificadores de propiedades sólo pueden aplicarse a determinados tipos de propiedades, aunque el lenguaje no lo impone. Por ejemplo, el tipo NumberAnimation proporcionado por QtQuick sólo animará propiedades de tipo numérico (como int o real). Si se intenta utilizar NumberAnimation con una propiedad no numérica, no se producirá ningún error, pero la propiedad no numérica no se animará. El comportamiento de un tipo de modificador de propiedad cuando se asocia a un tipo de propiedad concreto viene definido por su implementación.
Atributos de las señales
Una señal es una notificación de un objeto de que se ha producido algún evento: por ejemplo, ha cambiado una propiedad, se ha iniciado o detenido una animación o se ha descargado una imagen. El tipo MouseArea, por ejemplo, tiene una señal clicked que se emite cuando el usuario hace clic dentro del área del ratón.
Un objeto puede ser notificado a través de un manejador de señales cada vez que se emite una señal en particular. Un manejador de señales se declara con la sintaxis on<Señal> donde <Señal> es el nombre de la señal, con la primera letra en mayúscula. El manejador de señal debe declararse dentro de la definición del objeto que emite la señal, y el manejador debe contener el bloque de código JavaScript que se ejecutará cuando se invoque el manejador de señal.
Por ejemplo, el manejador de señal onClicked a continuación se declara dentro de la definición del objeto MouseArea, y se invoca cuando se hace clic en MouseArea, provocando que se imprima un mensaje de consola:
import QtQuick Item { width: 100; height: 100 MouseArea { anchors.fill: parent onClicked: { console.log("Click!") } } }
Definición de atributos de señal
Se puede definir una señal para un tipo en C++ registrando un Q_SIGNAL de una clase que, a su vez, se registra en el sistema de tipos de QML. Alternativamente, se puede definir una señal personalizada para un tipo de objeto en una declaración de objeto en un documento QML con la siguiente sintaxis:
signal <signalName>[([<parameterName>: <parameterType>[, ...]])]
Es un error intentar declarar dos señales o métodos con el mismo nombre en el mismo bloque de tipos. Sin embargo, una nueva señal puede reutilizar el nombre de una señal existente en el tipo. (Esto debe hacerse con precaución, ya que la señal existente puede quedar oculta y volverse inaccesible).
A continuación se muestran tres ejemplos de declaraciones de señales:
import QtQuick Item { signal clicked signal hovered() signal actionPerformed(action: string, actionResult: int) }
También puede especificar parámetros de señal en sintaxis de estilo de propiedad:
signal actionCanceled(string action)
Para ser coherente con las declaraciones de métodos, debe preferir las declaraciones de tipos utilizando dos puntos.
Si la señal no tiene parámetros, los corchetes "()" son opcionales. Si se utilizan parámetros, deben declararse los tipos de parámetros, como en el caso de los argumentos string y int para la señal actionPerformed anterior. Los tipos de parámetros permitidos son los mismos que los enumerados en Definición de atributos de propiedades en esta página.
Para emitir una señal, invócala como un método. Cualquier manejador de señal relevante será invocado cuando la señal sea emitida, y los manejadores pueden utilizar los nombres de los argumentos de señal definidos para acceder a los argumentos respectivos.
Señales de cambio de propiedad
Los tipos QML también proporcionan señales de cambio de propiedad integradas que se emiten cada vez que cambia el valor de una propiedad, como se ha descrito anteriormente en la sección sobre atributos de propiedad. Consulte la siguiente sección sobre gestores de señales de cambio de propiedades para obtener más información sobre la utilidad de estas señales y cómo utilizarlas.
Atributos de los manejadores de señales
Los manejadores de señales son un tipo especial de atributo de método, en el que el motor QML invoca la implementación del método cada vez que se emite la señal asociada. Al añadir una señal a una definición de objeto en QML, se añadirá automáticamente un manejador de señal asociado a la definición de objeto, que tiene, por defecto, una implementación vacía. Los clientes pueden proporcionar una implementación, para implementar la lógica del programa.
Considere el siguiente tipo SquareButton, cuya definición se proporciona en el archivo SquareButton.qml como se muestra a continuación, con las señales activated y deactivated:
// SquareButton.qml Rectangle { id: root signal activated(xPosition: real, yPosition: real) signal deactivated property int side: 100 width: side; height: side MouseArea { anchors.fill: parent onReleased: root.deactivated() onPressed: mouse => root.activated(mouse.x, mouse.y) } }
Estas señales podrían ser recibidas por cualquier objeto SquareButton en otro archivo QML en el mismo directorio, donde las implementaciones para los manejadores de señales son proporcionadas por el cliente:
// myapplication.qml SquareButton { onDeactivated: console.log("Deactivated!") onActivated: (xPosition, yPosition) => { console.log(`Activated at ${xPosition}, ${yPosition}`) } }
Los manejadores de señales no tienen que declarar sus tipos de parámetros porque la señal ya los especifica. La sintaxis de la función de flecha mostrada anteriormente no admite anotaciones de tipo.
Consulte el Sistema de Señales y Eventos Manejadores para más detalles sobre el uso de señales.
Manejadores de Señal de Cambio de Propiedad
Los manejadores de señal para la señal de cambio de propiedad toman la forma sintáctica on<Property>Changed donde <Property> es el nombre de la propiedad, con la primera letra en mayúscula. Por ejemplo, aunque la documentación del tipo TextInput no documenta una señal textChanged, esta señal está implícitamente disponible a través del hecho de que TextInput tiene una propiedad text y por lo tanto es posible escribir un manejador de señal onTextChanged para ser llamado cada vez que esta propiedad cambie:
import QtQuick TextInput { text: "Change this!" onTextChanged: console.log(`Text has changed to: ${text}`) }
Atributos de los métodos
Un método de un tipo de objeto es una función que puede ser llamada para realizar algún proceso o desencadenar otros eventos. Un método puede conectarse a una señal para que sea invocado automáticamente cada vez que se emita la señal. Consulte Sistema de señales y eventos manejadores para obtener más detalles.
Definición de atributos de métodos
Se puede definir un método para un tipo en C++ etiquetando una función de una clase que luego se registra en el sistema de tipos QML con Q_INVOKABLE o registrándola como Q_SLOT de la clase. Alternativamente, se puede añadir un método personalizado a una declaración de objeto en un documento QML con la siguiente sintaxis:
function <functionName>([<parameterName>[: <parameterType>][, ...]]) [: <returnType>] { <body> }
Se pueden añadir métodos a un tipo QML para definir bloques de código JavaScript independientes y reutilizables. Estos métodos pueden ser invocados internamente o por objetos externos.
A diferencia de las señales, no es necesario declarar los tipos de parámetros de los métodos, ya que por defecto son del tipo var. Sin embargo, debe declararlos para ayudar a qmlcachegen a generar un código más eficaz y mejorar su mantenimiento.
Intentar declarar dos métodos o señales con el mismo nombre en el mismo bloque de tipo es un error. Sin embargo, un nuevo método puede reutilizar el nombre de un método existente en el tipo. (Esto debe hacerse con precaución, ya que el método existente puede quedar oculto y volverse inaccesible).
A continuación se muestra un Rectangle con un método calculateHeight() que se llama al asignar el valor height:
import QtQuick Rectangle { id: rect function calculateHeight(): real { return rect.width / 2; } width: 100 height: calculateHeight() }
Si el método tiene parámetros, son accesibles por nombre dentro del método. Abajo, cuando se hace clic en MouseArea se invoca al método moveTo() que puede entonces referirse a los parámetros recibidos newX y newY para reposicionar el texto:
import QtQuick Item { width: 200; height: 200 MouseArea { anchors.fill: parent onClicked: mouse => label.moveTo(mouse.x, mouse.y) } Text { id: label function moveTo(newX: real, newY: real) { label.x = newX; label.y = newY; } text: "Move me!" } }
Propiedades adjuntas y manejadores de señales adjuntos
Las propiedadesadjuntas y los manejadores de señales adjuntos son mecanismos que permiten anotar objetos con propiedades adicionales o manejadores de señales que, de otro modo, no estarían disponibles para el objeto. En particular, permiten a los objetos acceder a propiedades o señales que son específicamente relevantes para el objeto individual.
Una implementación de tipos QML puede optar por crear un tipo adjunto en C++ con propiedades y señales particulares. A continuación, se pueden crear instancias de este tipo y adjuntarlas a objetos específicos en tiempo de ejecución, lo que permite a dichos objetos acceder a las propiedades y señales del tipo adjunto. Para acceder a ellas, se anteponen a las propiedades y a los respectivos manejadores de señales el nombre del tipo que se adjunta.
Las referencias a propiedades y manejadores adjuntos adoptan la siguiente forma sintáctica:
<AttachingType>.<propertyName> <AttachingType>.on<SignalName>
Por ejemplo, el tipo ListView tiene una propiedad adjunta ListView.isCurrentItem que está disponible para cada objeto delegado en ListView. Cada objeto delegado puede utilizarla para determinar si es el elemento seleccionado actualmente en la vista:
import QtQuick ListView { width: 240; height: 320 model: 3 delegate: Rectangle { width: 100; height: 30 color: ListView.isCurrentItem ? "red" : "yellow" } }
En este caso, el nombre del tipo adjunto es ListView y la propiedad en cuestión es isCurrentItem, por lo que la propiedad adjunta se denomina ListView.isCurrentItem.
Un manejador de señal adjunta se denomina de la misma manera. Por ejemplo, el manejador de señal adjunta Component.onCompleted se utiliza comúnmente para ejecutar algún código JavaScript cuando se ha completado el proceso de creación de un componente. En el ejemplo siguiente, una vez que ListModel se ha creado por completo, su controlador de señal Component.onCompleted se invocará automáticamente para rellenar el modelo:
import QtQuick ListView { width: 240; height: 320 model: ListModel { id: listModel Component.onCompleted: { for (let i = 0; i < 10; i++) { append({ Name: `Item ${i}` }) } } } delegate: Text { text: index } }
Dado que el nombre del tipo adjunto es Component y que ese tipo tiene una señal completed, el manejador de la señal adjunta se denomina Component.onCompleted.
Nota sobre el acceso a propiedades adjuntas y manejadores de señales
Un error común es asumir que las propiedades adjuntas y los manejadores de señal son directamente accesibles desde los hijos del objeto al que se han adjuntado estos atributos. Esto no es así. La instancia del tipo de adjunto sólo se adjunta a objetos específicos, no al objeto y a todos sus hijos.
Por ejemplo, a continuación se muestra una versión modificada del ejemplo anterior en el que se adjuntaban propiedades. Esta vez, el delegado es un Item y el Rectangle coloreado es un hijo de ese elemento:
import QtQuick ListView { width: 240; height: 320 model: 3 delegate: Item { width: 100; height: 30 Rectangle { width: 100; height: 30 color: ListView.isCurrentItem ? "red" : "yellow" // WRONG! This won't work. } } }
Esto no funciona como se esperaba porque ListView.isCurrentItem sólo se adjunta al objeto delegado raíz, y no a sus hijos. Dado que Rectangle es un hijo del delegado, en lugar de ser el propio delegado, no puede acceder a la propiedad adjunta isCurrentItem como ListView.isCurrentItem. En su lugar, el rectángulo debe acceder a isCurrentItem a través del delegado raíz:
ListView { delegate: Item { id: delegateItem width: 100; height: 30 Rectangle { width: 100; height: 30 color: delegateItem.ListView.isCurrentItem ? "red" : "yellow" // correct } } }
Ahora delegateItem.ListView.isCurrentItem se refiere correctamente a la propiedad adjunta isCurrentItem del delegado.
Atributos de enumeración
Las enumeraciones proporcionan un conjunto fijo de opciones con nombre. Pueden declararse en QML utilizando la palabra clave enum:
// MyText.qml Text { enum TextType { Normal, Heading } }
Como se ha indicado anteriormente, los tipos de enumeración (por ejemplo, TextType) y los valores (por ejemplo, Normal) deben comenzar con una letra mayúscula.
Se hace referencia a los valores mediante <Type>.<EnumerationType>.<Value> o <Type>.<Value>.
// MyText.qml Text { enum TextType { Normal, Heading } property int textType: MyText.TextType.Normal font.bold: textType === MyText.TextType.Heading font.pixelSize: textType === MyText.TextType.Heading ? 24 : 12 }
Encontrará más información sobre el uso de enumeraciones en QML en la documentación sobre Enumeraciones QML.
La posibilidad de declarar enumeraciones en QML se introdujo en Qt 5.10.
© 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.