Sistema de señales y eventos
Los componentes de la aplicación y de la interfaz de usuario necesitan comunicarse entre sí. Por ejemplo, un botón necesita saber que el usuario ha hecho clic sobre él. El botón puede cambiar de color para indicar su estado o ejecutar alguna lógica. Además, la aplicación necesita saber si el usuario hace clic en el botón. La aplicación puede necesitar retransmitir este evento de clic a otras aplicaciones.
QML tiene un mecanismo de señal y manejador, donde la señal es el evento y la señal se responde a través de un manejador de señal. Cuando se emite una señal, se invoca al manejador de señal correspondiente. Colocar lógica como un script u otras operaciones en el manejador permite al componente responder al evento.
Recepción de señales con manejadores de señales
Para recibir una notificación cuando se emite una señal determinada para un objeto concreto, la definición del objeto debe declarar un manejador de señales llamado on<Signal>, donde <Signal> es el nombre de la señal, con la primera letra en mayúscula. El manejador de señal debe contener el código JavaScript que se ejecutará cuando se invoque el manejador de señal.
Por ejemplo, el tipo Button del módulo Qt Quick Controls tiene una señal clicked, que se emite cada vez que se pulsa el botón. En este caso, el manejador de señal para recibir esta señal debería ser onClicked. En el siguiente ejemplo, cada vez que se pulsa el botón, se invoca el manejador onClicked, aplicando un color aleatorio al padre Rectangle:
import QtQuick import QtQuick.Controls Rectangle { id: rect width: 250; height: 250 Button { anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter text: "Change color!" onClicked: { rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1); } } }
Nota: Aunque los manejadores de señales se parecen un poco a las funciones de JavaScript, no debe llamarlos directamente. Si necesitas compartir código entre los manejadores de señales y otras funcionalidades, refactorízalo en una función separada. De lo contrario, emita siempre la señal si desea que se llame al manejador de señales. Puede haber múltiples manejadores, en diferentes ámbitos, para la misma señal.
Controladores de señales de cambio de propiedad
Una señal se emite automáticamente cuando cambia el valor de una propiedad QML. Este tipo de señal es una señal de cambio de propiedad y los manejadores de señales para estas señales se escriben de la forma on<Property>Changed, donde <Property> es el nombre de la propiedad, con la primera letra en mayúscula.
Por ejemplo, el tipo MouseArea tiene una propiedad pressed. Para recibir una notificación cada vez que esta propiedad cambie, escriba un manejador de señales llamado onPressedChanged:
import QtQuick Rectangle { id: rect width: 100; height: 100 TapHandler { onPressedChanged: console.log("taphandler pressed?", pressed) } }
Aunque la documentación de TapHandler no documenta un manejador de señales llamado onPressedChanged, la señal se proporciona implícitamente por el hecho de que existe la propiedad pressed.
Parámetros de la señal
Las señales pueden tener parámetros. Para acceder a ellos, debes asignar una función al manejador. Tanto las funciones de flecha como las funciones anónimas funcionan.
Para los siguientes ejemplos, considere un componente Status con una señal errorOccurred (consulte Adición de señales a tipos QML personalizados para obtener más información sobre cómo se pueden añadir señales a componentes QML).
// Status.qml import QtQuick Item { id: myitem signal errorOccurred(message: string, line: int, column: int) }
Status { onErrorOccurred: (mgs, line, col) => console.log(`${line}:${col}: ${msg}`) }
Nota: Los nombres de los parámetros formales de la función no tienen por qué coincidir con los de la señal.
Si no es necesario manejar todos los parámetros, es posible omitir los últimos:
Status { onErrorOccurred: message => console.log(message) }
No es posible omitir los parámetros principales que le interesen, pero puede utilizar algún nombre de marcador de posición para indicar a los lectores que no son importantes:
Status { onErrorOccurred: (_, _, col) => console.log(`Error happened at column ${col}`) }
Nota: En lugar de utilizar una función, es posible, aunque desaconsejable, utilizar un bloque de código plano. En ese caso, todos los parámetros de la señal se inyectan en el ámbito del bloque. Sin embargo, esto puede hacer que el código sea difícil de leer, ya que no está claro de dónde proceden los parámetros, y da lugar a búsquedas más lentas en el motor QML. Inyectar parámetros de esta forma está obsoleto y provocará advertencias en tiempo de ejecución si el parámetro se utiliza realmente.
Uso del objeto especial arguments
En JavaScript se puede hacer referencia al objeto especial arguments, que, cuando está disponible, permite acceder a los valores de los argumentos pasados a una función no-arrow como un objeto tipo array.
Suele estar disponible en el cuerpo de una función o bloque de código que se asigna a un manejador de señales.
Cuando se asigna un bloque de código o una función anónima al manejador de señales, el objeto especial arguments proporcionará los argumentos pasados por la señal.
Por ejemplo, ambos de los siguientes imprimirán [object Arguments] world undefined:
import QtQml QtObject { id: root signal hello(message: string) onHello: { console.log(arguments, arguments[0], arguments[1]) } Component.onCompleted: root.hello("world") }
import QtQml QtObject { id: root signal hello(message: string) onHello: function () { console.log(arguments, arguments[0], arguments[1]) } Component.onCompleted: root.hello("world") }
El comportamiento será diferente cuando se asigne una función de flecha al manejador de señales. En ese caso, seguirá siendo posible acceder al objeto especial arguments, pero será un objeto tipo array vacío.
Por ejemplo, lo siguiente imprimirá [object Arguments] undefined undefined:
import QtQml QtObject { id: root signal hello(message: string) onHello: () => { console.log(arguments, arguments[0], arguments[1]) } Component.onCompleted: root.hello("world") }
La diferencia de comportamiento se debe a la forma en que el objeto especial arguments interactúa con las funciones de flecha, pero es coherente con el comportamiento general de los enlaces.
Por especificación, una función de flecha no lleva su propio objeto especial arguments. Dado que una función de flecha todavía toma prestado de su contexto envolvente, puede tomar prestado el objeto especial arguments si hay uno disponible.
Una vinculación proporciona su propio ámbito en la evaluación. En concreto, la recuperación de la función de flecha subyacente se realiza en el ámbito proporcionado por la evaluación de la vinculación.
En el ámbito de la vinculación no se proporciona ningún argumento, de modo que un objeto especial arguments vacío estará disponible y será tomado prestado por la función de flecha en la recuperación.
Como una función que no es de flecha sí proporciona el objeto especial arguments en su propio ámbito, puede referirse a los argumentos que se proporcionaron a la propia función subyacente, que son los argumentos reenviados proporcionados por la señal.
En general, debería evitarse el uso del objeto especial arguments en favor del uso de parámetros con nombre, que son más explícitos y funcionan de forma coherente independientemente del uso de una función con flecha o sin flecha.
Uso del tipo Conexiones
En algunos casos puede ser deseable acceder a una señal fuera del objeto que la emite. Para estos propósitos, el módulo QtQuick proporciona el tipo Connections para conectarse a señales de objetos arbitrarios. Un objeto Connections puede recibir cualquier señal de su target especificado.
Por ejemplo, el manejador onClicked del ejemplo anterior podría haber sido recibido por la raíz Rectangle en su lugar, colocando el manejador onClicked en un objeto Connections que tenga su target establecido en button:
import QtQuick import QtQuick.Controls Rectangle { id: rect width: 250; height: 250 Button { id: button anchors.bottom: parent.bottom anchors.horizontalCenter: parent.horizontalCenter text: "Change color!" } Connections { target: button function onClicked() { rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1); } } }
Manejadores de señal adjuntos
Un manejador de señal adjunto recibe una señal de un tipo adjunto en lugar del objeto dentro del cual se declara el manejador.
Por ejemplo, Component.onCompleted es un controlador de señales adjunto. Suele utilizarse para ejecutar código JavaScript cuando finaliza su proceso de creación. He aquí un ejemplo:
import QtQuick Rectangle { width: 200; height: 200 color: Qt.rgba(Qt.random(), Qt.random(), Qt.random(), 1) Component.onCompleted: { console.log("The rectangle's color is", color) } }
El manejador onCompleted no está respondiendo a una señal completed del tipo Rectangle. En su lugar, el motor QML ha adjuntado automáticamente al objeto Rectangle un objeto del tipo Component con una señal completed. El motor emite esta señal cuando se crea el objeto Rectangle, activando así el controlador de señales Component.onCompleted.
Los gestores de señales adjuntos permiten notificar a los objetos determinadas señales que son importantes para cada uno de ellos. Si no existiera un gestor de señales adjunto a Component.onCompleted, por ejemplo, un objeto no podría recibir esta notificación sin registrarse para alguna señal especial de algún objeto especial. El mecanismo del manejador de señales adjunto permite a los objetos recibir señales particulares sin código adicional.
Consulte Propiedades adjuntas y manejadores de señales adjuntos para obtener más información sobre los manejadores de señales adjuntos.
Añadir señales a tipos QML personalizados
Se pueden añadir señales a tipos QML personalizados mediante la palabra clave signal.
La sintaxis para definir una nueva señal es:
signal <name>[([<type> <parameter name>[, ...]])]
Una señal se emite invocando a la señal como método.
Por ejemplo, el código siguiente está definido en un archivo llamado SquareButton.qml. El objeto raíz Rectangle tiene una señal activated, que se emite siempre que el objeto hijo TapHandler es tapped. En este ejemplo concreto, la señal activada se emite con las coordenadas x e y del clic del ratón:
// SquareButton.qml import QtQuick Rectangle { id: root signal activated(real xPosition, real yPosition) property point mouseXY property int side: 100 width: side; height: side TapHandler { id: handler onTapped: root.activated(root.mouseXY.x, root.mouseXY.y) onPressedChanged: root.mouseXY = handler.point.position } }
Ahora cualquier objeto del SquareButton puede conectarse a la señal activated utilizando un manejador de señal onActivated:
// myapplication.qml SquareButton { onActivated: (xPosition, yPosition) => console.log(`Activated at {xPosition}, ${yPosition}`) }
Consulte Atributos de señal para obtener más detalles sobre la escritura de señales para tipos QML personalizados.
Conexión de señales a métodos y señales
Los objetos Signal tienen un método connect() para conectar una señal a un método o a otra señal. Cuando se conecta una señal a un método, éste se invoca automáticamente cada vez que se emite la señal. Este mecanismo permite que una señal sea recibida por un método en lugar de por un manejador de señales.
A continuación, la señal messageReceived se conecta a tres métodos mediante el método connect():
import QtQuick Rectangle { id: relay signal messageReceived(string person, string notice) Component.onCompleted: { relay.messageReceived.connect(sendToPost) relay.messageReceived.connect(sendToTelegraph) relay.messageReceived.connect(sendToEmail) relay.messageReceived("Tom", "Happy Birthday") } function sendToPost(person: string, notice: string) { console.log(`Sending to post: ${person}, ${notice}`) } function sendToTelegraph(person: string, notice: string) { console.log(`Sending to telegraph: ${person}, ${notice}`) } function sendToEmail(person: string, notice: string) { console.log(`Sending to email: ${person}, ${notice}`) } }
En muchos casos es suficiente recibir señales a través de manejadores de señales en lugar de utilizar la función connect(). Sin embargo, el uso del método connect permite que una señal sea recibida por múltiples métodos, como se ha mostrado anteriormente, lo que no sería posible con los manejadores de señales, ya que deben tener un nombre único. Además, el método connect es útil cuando se conectan señales a objetos creados dinámicamente.
Existe un método disconnect() correspondiente para eliminar las señales conectadas:
Rectangle { id: relay //... function removeTelegraphSignal() { relay.messageReceived.disconnect(sendToTelegraph) } }
Conectar señal a señal
Mediante la conexión de señales a otras señales, el método connect() puede formar diferentes cadenas de señales.
import QtQuick Rectangle { id: forwarder width: 100; height: 100 signal send() onSend: console.log("Send clicked") TapHandler { id: mousearea anchors.fill: parent onTapped: console.log("Mouse clicked") } Component.onCompleted: { mousearea.tapped.connect(send) } }
Siempre que se emita la señal tapped de TapHandler, automáticamente se emitirá también la señal send.
output:
MouseArea clicked
Send clickedNota: Las conexiones a objetos de función permanecerán vivas mientras el emisor de la señal esté vivo. Este comportamiento es análogo a la versión de 3 argumentos de QObject::connect() en C++.
Window { visible: true width: 400 height: 400 Item { id: item property color globalColor: "red" Button { text: "Change global color" onPressed: { item.globalColor = item.globalColor === Qt.color("red") ? "green" : "red" } } Button { x: 150 text: "Clear rectangles" onPressed: repeater.model = 0 } Repeater { id: repeater model: 5 Rectangle { id: rect color: "red" width: 50 height: 50 x: (width + 2) * index + 2 y: 100 Component.onCompleted: { if (index % 2 === 0) { item.globalColorChanged.connect(() => { color = item.globalColor }) } } } } } }
En el ejemplo anterior, el objetivo es cambiar el color de cada rectángulo par para que siga un color global. Para conseguirlo, para cada rectángulo par, se hace una conexión entre la señal globalColorChanged y una función para establecer el color del rectángulo. Esto funciona como se espera mientras los rectángulos están vivos. Sin embargo, una vez que se pulsa el botón de borrar, los rectángulos desaparecen pero la función que maneja la señal sigue siendo llamada cada vez que se emite la señal. Esto se puede ver por los mensajes de error lanzados por la función que intenta ejecutarse en segundo plano al cambiar el color global.
En la configuración actual, las conexiones sólo se destruyen cuando se destruye el elemento que contiene globalColor. Para evitar que las conexiones persistan, pueden desconectarse explícitamente cuando se destruyen los rectángulos.
© 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.