Focus sur le clavier Qt Quick
Lorsqu'une touche est enfoncée ou relâchée, un événement de touche est généré et transmis à l'élément focalisé Qt Quick Item . Pour faciliter la construction de composants réutilisables et pour traiter certains des cas propres aux interfaces utilisateur fluides, les éléments de Qt Quick ajoutent une extension basée sur le champ d'application au modèle traditionnel de focalisation du clavier de Qt.
Aperçu de la gestion des touches
Lorsque l'utilisateur appuie sur une touche ou la relâche, il se produit ce qui suit :
- Qt reçoit l'action de la touche et génère un événement de touche.
- Si un site QQuickWindow est le site focus window de l'application, l'événement touche lui est transmis.
- L'événement clé est transmis par la scène à l'élément Item qui est au centre de l 'attention. Si aucun élément n'a le focus actif, l'événement clé est ignoré.
- Si le QQuickItem avec le focus actif accepte l'événement clé, la propagation s'arrête. Sinon, l'événement est envoyé au parent de l'élément jusqu'à ce que l'événement soit accepté ou que l'élément racine soit atteint.
Si, dans l'exemple suivant, le type
Rectanglea le focus actif et que la toucheAest pressée, l'événement ne sera pas propagé plus loin. En appuyant sur la toucheB, l'événement se propagera à l'élément racine et sera donc ignoré.Rectangle { width: 100; height: 100 focus: true Keys.onPressed: (event)=> { if (event.key == Qt.Key_A) { console.log('Key A was pressed'); event.accepted = true; } } }
- Si la racine Item est atteinte, l'événement touche est ignored et la gestion normale des touches Qt se poursuit.
Voir également les pages Keys attached property et KeyNavigation attached property.
Interrogation de l'élément de focalisation actif
La propriété Item::activeFocus permet de savoir si un site Item a le focus actif ou non. Par exemple, nous avons ici un type Text dont le texte est déterminé par la présence ou non du focus actif.
Text { text: activeFocus ? "I have active focus!" : "I do not have active focus" }
Acquisition de la focalisation et des portées de focalisation
Un type Item demande le focus en définissant la propriété focus sur true.
Dans des cas très simples, il suffit parfois de définir la propriété focus. Si nous exécutons l'exemple suivant avec l'outil qml, nous constatons que le type keyHandler a le focus actif et que le fait d'appuyer sur les touches A, B ou C modifie le texte de manière appropriée.
Rectangle { color: "lightsteelblue"; width: 240; height: 25 Text { id: myText } Item { id: keyHandler focus: true Keys.onPressed: (event)=> { if (event.key == Qt.Key_A) myText.text = 'Key A was pressed' else if (event.key == Qt.Key_B) myText.text = 'Key B was pressed' else if (event.key == Qt.Key_C) myText.text = 'Key C was pressed' } } }

Cependant, si l'exemple ci-dessus devait être utilisé comme composant réutilisable ou importé, cette simple utilisation de la propriété focus n'est plus suffisante.
Pour le démontrer, nous créons deux instances de notre composant précédemment défini et nous donnons la priorité à la première. L'objectif est que lorsque les touches A, B ou C sont pressées, le premier des deux composants reçoive l'événement et réagisse en conséquence.
Le code qui importe et crée deux instances de MyWidget :
//Window code that imports MyWidget Rectangle { id: window color: "white"; width: 240; height: 150 Column { anchors.centerIn: parent; spacing: 15 MyWidget { focus: true //set this MyWidget to receive the focus color: "lightblue" } MyWidget { color: "palegreen" } } }
Le code de MyWidget :
Rectangle { id: widget color: "lightsteelblue"; width: 175; height: 25; radius: 10; antialiasing: true Text { id: label; anchors.centerIn: parent} focus: true Keys.onPressed: (event)=> { if (event.key == Qt.Key_A) label.text = 'Key A was pressed' else if (event.key == Qt.Key_B) label.text = 'Key B was pressed' else if (event.key == Qt.Key_C) label.text = 'Key C was pressed' } }
Nous voulons que le premier objet MyWidget ait le focus, nous définissons donc sa propriété focus à true. Cependant, en exécutant le code, il peut arriver que le second widget reçoive le focus.

En examinant les codes MyWidget et window, le problème est évident - il y a trois types qui définissent la propriété focus sur true. Les deux MyWidgetdéfinissent la propriété focus sur true et le composant window définit également le focus. En fin de compte, un seul type peut avoir le focus clavier, et le système doit décider quel type reçoit le focus. Étant donné que QML ne garantit pas quel élément aura ses propriétés initialisées en premier, il se peut que le dernier MyWidget reçoive le focus initial.
Ce problème est dû à la visibilité. Le composant MyWidget aimerait avoir le focus, mais il ne peut pas le contrôler lorsqu'il est importé ou réutilisé. De même, le composant window n'a pas la possibilité de savoir si ses composants importés demandent le focus.
Pour résoudre ce problème, QML introduit un concept connu sous le nom de portée du focus. Pour les utilisateurs existants de Qt, une portée de focus est comme un proxy de focus automatique. Une portée de focus est créée en déclarant le type FocusScope.
Dans l'exemple suivant, un type FocusScope est ajouté au composant et le résultat visuel est montré.
FocusScope { //FocusScope needs to bind to visual properties of the Rectangle property alias color: rectangle.color x: rectangle.x; y: rectangle.y width: rectangle.width; height: rectangle.height Rectangle { id: rectangle anchors.centerIn: parent color: "lightsteelblue"; width: 175; height: 25; radius: 10; antialiasing: true Text { id: label; anchors.centerIn: parent } focus: true Keys.onPressed: (event)=> { if (event.key == Qt.Key_A) label.text = 'Key A was pressed' else if (event.key == Qt.Key_B) label.text = 'Key B was pressed' else if (event.key == Qt.Key_C) label.text = 'Key C was pressed' } } }

D'un point de vue conceptuel, les champs de focalisation sont assez simples.
- Dans chaque champ de focalisation, un objet peut avoir
Item::focusdéfini àtrue. Si plus d'un Item a la propriétéfocusdéfinie, le dernier type à définir la propriétéfocusaura la focalisation et les autres ne seront pas définis, comme lorsqu'il n'y a pas de champ de focalisation. - Lorsqu'un champ de focalisation reçoit la focalisation active, le type contenu dont la propriété
focusest définie (le cas échéant) reçoit également la focalisation active. Si ce type est également un FocusScope, le comportement de procuration se poursuit. L'étendue du focus et l'élément sous-focalisé auront tous deux la propriétéactiveFocusdéfinie.
Notez que, puisque le type FocusScope n'est pas un type visuel, les propriétés de ses enfants doivent être exposées à l'élément parent du type FocusScope. Les mises en page et les types de positionnement utiliseront ces propriétés visuelles et de style pour créer la mise en page. Dans notre exemple, le type Column ne peut pas afficher correctement les deux widgets car le type FocusScope ne possède pas de propriétés visuelles propres. Le composant MyWidget se lie directement aux propriétés de rectangle pour permettre au type Column de créer la mise en page contenant les enfants de FocusScope.
Jusqu'à présent, l'exemple a sélectionné le deuxième composant de manière statique. Il est maintenant trivial d'étendre ce composant pour le rendre cliquable et de l'ajouter à l'application d'origine. Nous continuons à définir l'un des widgets comme étant focalisé par défaut. Désormais, le fait de cliquer sur l'un des MyClickableWidget lui donne le focus et l'autre widget perd le focus.
Le code qui importe et crée deux instances de MyClickableWidget :
Rectangle { id: window color: "white"; width: 240; height: 150 Column { anchors.centerIn: parent; spacing: 15 MyClickableWidget { focus: true //set this MyWidget to receive the focus color: "lightblue" } MyClickableWidget { color: "palegreen" } } }
Le code de MyClickableWidget :
FocusScope { id: scope //FocusScope needs to bind to visual properties of the children property alias color: rectangle.color x: rectangle.x; y: rectangle.y width: rectangle.width; height: rectangle.height Rectangle { id: rectangle anchors.centerIn: parent color: "lightsteelblue"; width: 175; height: 25; radius: 10; antialiasing: true Text { id: label; anchors.centerIn: parent } focus: true Keys.onPressed: (event)=> { if (event.key == Qt.Key_A) label.text = 'Key A was pressed' else if (event.key == Qt.Key_B) label.text = 'Key B was pressed' else if (event.key == Qt.Key_C) label.text = 'Key C was pressed' } } MouseArea { anchors.fill: parent; onClicked: { scope.focus = true } } }

Lorsqu'un QML Item renonce explicitement au focus (en définissant sa propriété focus sur false alors qu'il a le focus actif), le système ne sélectionne pas automatiquement un autre type pour recevoir le focus. En d'autres termes, il est possible qu'il n'y ait pas de focus actif.
Voir Qt Quick Examples - Key Interaction pour une démonstration du déplacement du focus clavier entre plusieurs zones à l'aide des types FocusScope.
Utilisations avancées des portées de focus
Les portées de focus permettent de répartir facilement le focus sur l'allocation. Plusieurs éléments QML l'utilisent à cet effet.
ListViewPar exemple, la balise de focus, est elle-même une balise de focus. En général, cela ne se remarque pas car ListView n'a généralement pas d'enfants visuels ajoutés manuellement. En étant une portée de focalisation, ListView peut focaliser l'élément de liste actuel sans se soucier de l'effet que cela aura sur le reste de l'application. Cela permet au délégué de l'élément courant de réagir aux pressions de touches.
L'exemple suivant montre comment cela fonctionne. L'appui sur la touche Return imprime le nom de l'élément de la liste en cours.
Rectangle { color: "lightsteelblue"; width: 100; height: 50 ListView { anchors.fill: parent focus: true model: ListModel { ListElement { name: "Bob" } ListElement { name: "John" } ListElement { name: "Michael" } } delegate: FocusScope { width: childrenRect.width; height: childrenRect.height x:childrenRect.x; y: childrenRect.y TextInput { focus: true text: name Keys.onReturnPressed: console.log(name) } } } }

Bien que l'exemple soit simple, il se passe beaucoup de choses dans les coulisses. Chaque fois que l'élément courant change, ListView définit la propriété Item::focus du délégué. Comme ListView est une portée de focus, cela n'affecte pas le reste de l'application. Toutefois, si le site ListView a lui-même un focus actif, le délégué recevra également un focus actif. Dans cet exemple, le type racine du délégué est également une portée de focalisation, ce qui donne une focalisation active au type TextInput qui effectue le travail de gestion de la clé Return.
Toutes les classes de vues QML, telles que PathView et GridView, se comportent de la même manière pour permettre la gestion des touches dans leurs délégués respectifs.
© 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.