Système de signaux et de gestionnaires d'événements
Les composants de l'application et de l'interface utilisateur doivent communiquer entre eux. Par exemple, un bouton doit savoir que l'utilisateur a cliqué dessus. Le bouton peut changer de couleur pour indiquer son état ou exécuter une certaine logique. De même, l'application doit savoir si l'utilisateur clique sur le bouton. L'application peut avoir besoin de relayer cet événement de clic à d'autres applications.
QML dispose d'un mécanisme de signal et de gestionnaire, où le signal est l'événement et le signal est traité par un gestionnaire de signal. Lorsqu'un signal est émis, le gestionnaire de signal correspondant est invoqué. Le fait de placer une logique telle qu'un script ou d'autres opérations dans le gestionnaire permet au composant de répondre à l'événement.
Réception de signaux avec des gestionnaires de signaux
Pour recevoir une notification lorsqu'un signal particulier est émis pour un objet particulier, la définition de l'objet doit déclarer un gestionnaire de signal nommé on<Signal>, où <Signal> est le nom du signal, avec la première lettre en majuscule. Le gestionnaire de signal doit contenir le code JavaScript à exécuter lorsque le gestionnaire de signal est invoqué.
Par exemple, le type Button du module Qt Quick Controls possède un signal clicked, qui est émis chaque fois que le bouton est cliqué. Dans ce cas, le gestionnaire de signal pour la réception de ce signal doit être onClicked. Dans l'exemple ci-dessous, chaque fois que le bouton est cliqué, le gestionnaire onClicked est invoqué, appliquant une couleur aléatoire au parent 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); } } }
Remarque : même si les gestionnaires de signaux ressemblent un peu à des fonctions JavaScript, vous ne devez pas les appeler directement. Si vous devez partager du code entre les gestionnaires de signaux et d'autres fonctionnalités, refaites-le dans une fonction distincte. Sinon, émettez toujours le signal si vous voulez que le gestionnaire de signal soit appelé. Il peut y avoir plusieurs gestionnaires, dans des domaines différents, pour le même signal.
Gestionnaires de signaux de changement de propriété
Un signal est automatiquement émis lorsque la valeur d'une propriété QML change. Ce type de signal est un signal de changement de propriété et les gestionnaires de ces signaux sont écrits sous la forme on<Property>Changed, où <Property> est le nom de la propriété, avec la première lettre en majuscule.
Par exemple, le type MouseArea possède une propriété pressed. Pour recevoir une notification chaque fois que cette propriété change, écrivez un gestionnaire de signal nommé onPressedChanged:
import QtQuick Rectangle { id: rect width: 100; height: 100 TapHandler { onPressedChanged: console.log("taphandler pressed?", pressed) } }
Même si la documentation de TapHandler ne documente pas de gestionnaire de signal nommé onPressedChanged, le signal est implicitement fourni par le fait que la propriété pressed existe.
Paramètres du signal
Les signaux peuvent avoir des paramètres. Pour y accéder, vous devez assigner une fonction au gestionnaire. Les fonctions fléchées et les fonctions anonymes fonctionnent toutes deux.
Pour les exemples suivants, considérons un composant Status avec un signal errorOccurred (voir Ajouter des signaux aux types QML personnalisés pour plus d'informations sur la façon dont les signaux peuvent être ajoutés aux composants 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}`) }
Remarque : les noms des paramètres formels de la fonction ne doivent pas nécessairement correspondre à ceux du signal.
Si vous n'avez pas besoin de traiter tous les paramètres, il est possible d'omettre ceux qui se trouvent à la fin :
Status { onErrorOccurred: message => console.log(message) }
Il n'est pas possible d'omettre les paramètres principaux qui vous intéressent, mais vous pouvez utiliser un nom générique pour indiquer aux lecteurs qu'ils ne sont pas importants :
Status { onErrorOccurred: (_, _, col) => console.log(`Error happened at column ${col}`) }
Note : Au lieu d'utiliser une fonction, il est possible, mais déconseillé, d'utiliser un bloc de code simple. Dans ce cas, tous les paramètres du signal sont injectés dans la portée du bloc. Cependant, cela peut rendre le code difficile à lire car l'origine des paramètres n'est pas claire, et cela ralentit les recherches dans le moteur QML. L'injection de paramètres de cette manière est déconseillée et provoquera des avertissements d'exécution si le paramètre est réellement utilisé.
Utilisation de l'objet spécial arguments
En JavaScript, vous pouvez faire référence à l'objet spécial arguments qui, lorsqu'il est disponible, permet d'accéder aux valeurs des arguments passés à une fonction non fléchée sous la forme d'un objet de type tableau.
Il est généralement disponible dans le corps d'une fonction ou d'un bloc de code affecté à un gestionnaire de signaux.
Lorsqu'un bloc de code ou une fonction anonyme est affecté au gestionnaire de signal, l'objet spécial arguments fournit les arguments transmis par le signal.
Par exemple, les deux objets suivants imprimeront [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") }
Le comportement sera différent si une fonction fléchée est assignée au gestionnaire de signal. Dans ce cas, il sera toujours possible d'accéder à l'objet spécial arguments, mais il s'agira d'un objet vide de type tableau.
Par exemple, ce qui suit imprimera [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 différence de comportement est due à la manière dont l'objet spécial arguments interagit avec les fonctions fléchées, mais elle est cohérente avec le comportement général des liaisons.
Par spécification, une fonction flèche ne porte pas son propre objet spécial arguments. Étant donné qu'une fonction fléchée emprunte toujours au contexte qui l'entoure, elle peut emprunter l'objet spécial arguments s'il en existe un.
Une liaison fournit sa propre portée lors de l'évaluation. En particulier, la récupération de la fonction fléchée sous-jacente est effectuée dans la portée fournie par l'évaluation de la liaison.
Dans la portée de la liaison, aucun argument n'est fourni, de sorte qu'un objet spécial arguments vide sera disponible et emprunté par la fonction de flèche lors de la récupération.
Étant donné qu'une fonction non fléchée fournit l'objet spécial arguments dans sa propre portée, elle peut se référer aux arguments qui ont été fournis à la fonction sous-jacente elle-même, qui sont les arguments transmis fournis par le signal.
L'utilisation de l'objet spécial arguments doit généralement être évitée au profit de l'utilisation de paramètres nommés, qui sont plus explicites et fonctionnent de manière cohérente, indépendamment de l'utilisation d'une fonction fléchée ou non fléchée.
Utilisation du type Connections
Dans certains cas, il peut être souhaitable d'accéder à un signal en dehors de l'objet qui l'émet. À cette fin, le module QtQuick fournit le type Connections pour se connecter aux signaux d'objets arbitraires. Un objet Connections peut recevoir n'importe quel signal de l'objet target spécifié.
Par exemple, le gestionnaire onClicked de l'exemple précédent aurait pu être reçu par la racine Rectangle en plaçant le gestionnaire onClicked dans un objet Connections dont le target est défini sur le 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); } } }
Gestionnaires de signaux attachés
Un gestionnaire de signal attaché reçoit un signal d'un type d'attachement plutôt que de l'objet dans lequel le gestionnaire est déclaré.
Par exemple, Component.onCompleted est un gestionnaire de signal attaché. Il est souvent utilisé pour exécuter du code JavaScript lorsque son processus de création est terminé. En voici un exemple :
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) } }
Le gestionnaire onCompleted ne répond pas à un signal completed du type Rectangle. Au lieu de cela, un objet du type Component attaching avec un signal completed a été automatiquement attaché à l'objet Rectangle par le moteur QML. Le moteur émet ce signal lorsque l'objet Rectangle est créé, ce qui déclenche le gestionnaire de signal Component.onCompleted.
Les gestionnaires de signaux attachés permettent aux objets d'être notifiés de signaux particuliers qui sont significatifs pour chaque objet individuel. S'il n'y avait pas de gestionnaire de signal attaché à Component.onCompleted, par exemple, un objet ne pourrait pas recevoir cette notification sans s'enregistrer pour un signal spécial provenant d'un objet spécial. Le mécanisme de gestion des signaux attachés permet aux objets de recevoir des signaux particuliers sans code supplémentaire.
Voir Propriétés attachées et Gestionnaires de signaux attachés pour plus d'informations sur les gestionnaires de signaux attachés.
Ajout de signaux aux types QML personnalisés
Les signaux peuvent être ajoutés aux types QML personnalisés par le biais du mot-clé signal.
La syntaxe pour définir un nouveau signal est la suivante :
signal <name>[([<type> <parameter name>[, ...]])]
Un signal est émis en invoquant le signal en tant que méthode.
Par exemple, le code ci-dessous est défini dans un fichier nommé SquareButton.qml. L'objet racine Rectangle possède un signal activated, qui est émis chaque fois que l'enfant TapHandler est tapped. Dans cet exemple particulier, le signal activé est émis avec les coordonnées x et y du clic de la souris :
// 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 } }
Désormais, tous les objets de SquareButton peuvent se connecter au signal activated à l'aide d'un gestionnaire de signal onActivated:
// myapplication.qml SquareButton { onActivated: (xPosition, yPosition) => console.log(`Activated at {xPosition}, ${yPosition}`) }
Voir Attributs de signal pour plus de détails sur l'écriture de signaux pour les types QML personnalisés.
Connexion des signaux aux méthodes et aux signaux
Les objets signal disposent d'une méthode connect() permettant de connecter un signal à une méthode ou à un autre signal. Lorsqu'un signal est connecté à une méthode, celle-ci est automatiquement invoquée lorsque le signal est émis. Ce mécanisme permet à un signal d'être reçu par une méthode plutôt que par un gestionnaire de signal.
Ci-dessous, le signal messageReceived est connecté à trois méthodes à l'aide de la méthode 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}`) } }
Dans de nombreux cas, il suffit de recevoir des signaux par l'intermédiaire de gestionnaires de signaux plutôt que d'utiliser la fonction connect(). Cependant, l'utilisation de la méthode connect permet à un signal d'être reçu par plusieurs méthodes, comme indiqué précédemment, ce qui ne serait pas possible avec les gestionnaires de signaux car ils doivent être nommés de manière unique. La méthode connect est également utile pour connecter des signaux à des objets créés dynamiquement.
Il existe une méthode disconnect() correspondante pour supprimer les signaux connectés :
Rectangle { id: relay //... function removeTelegraphSignal() { relay.messageReceived.disconnect(sendToTelegraph) } }
Connecter un signal à un autre signal
En connectant des signaux à d'autres signaux, la méthode connect() permet de former différentes chaînes de signaux.
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) } }
Chaque fois que le signal tapped de TapHandler est émis, le signal send est automatiquement émis.
output:
MouseArea clicked
Send clickedRemarque : les connexions aux objets fonction restent actives tant que l'émetteur du signal est en vie. Ce comportement est analogue à la version à 3 arguments 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 }) } } } } } }
Dans l'exemple artificiel ci-dessus, l'objectif est d'inverser la couleur de chaque rectangle pair pour qu'elle suive une couleur globale. Pour ce faire, pour chaque rectangle pair, une connexion est établie entre le signal globalColorChanged et une fonction permettant de définir la couleur du rectangle. Cela fonctionne comme prévu tant que les rectangles sont vivants. Cependant, une fois que l'on a appuyé sur le bouton "clear", les rectangles ont disparu, mais la fonction qui gère le signal est toujours appelée à chaque fois que le signal est émis. C'est ce que montrent les messages d'erreur envoyés par la fonction qui tente de s'exécuter en arrière-plan lors de la modification de la couleur globale.
Dans la configuration actuelle, les connexions ne sont détruites qu'une fois que l'élément contenant globalColor est détruit. Pour éviter que les connexions ne perdurent, elles peuvent être explicitement déconnectées lors de la destruction des rectangles.
© 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.