Qt Quick Controls - Éditeur de texte
Une application d'édition de texte enrichi utilisant Qt Quick Controls.
L'exemple d'éditeur de texte permet l'édition WYSIWYG d'un fichier HTML, Markdown ou de texte brut. L'application propose deux interfaces utilisateur : l'une pour les grands écrans, et une interface simplifiée pour les petits appareils tactiles. Les deux sont en QML « pur ». La classe texteditor.cpp contient la fonction main(), qui appelle QFontDatabase::addApplicationFont() pour ajouter une police d'icônes. (FontLoader serait une autre façon d'obtenir le même résultat.)
Interface utilisateur de bureau

La version de bureau est un éditeur de texte complet permettant de mettre en forme du texte, ainsi que d’ouvrir et d’enregistrer des fichiers HTML, Markdown et de texte brut.
Dans le modèle de conception MVC (modèle-vue-contrôle), la couche de contrôle comprend l’ensemble des opérations pouvant être effectuées. Dans Qt Quick Controls, le type ` Action ` est utilisé pour encapsuler une opération ou une commande unique. Par conséquent, nous commençons par un ensemble d’objets `Action` :
Action {
id: openAction
text: qsTr("&Open")
shortcut: StandardKey.Open
onTriggered: {
if (textArea.textDocument.modified)
discardDialog.open()
else
openDialog.open()
}
}Action L’ FileDialog, qui permet d’ouvrir un fichier, doit d’abord demander à l’utilisateur si le document existant a été modifié, afin d’éviter de perdre les modifications apportées par l’utilisateur. Sinon, elle ouvre simplement l’ déclarée plus bas.
L'Action d'enregistrement du fichier n'est activée que s'il y a des modifications à enregistrer :
Action {
id: saveAction
text: qsTr("&Save…")
shortcut: StandardKey.Save
enabled: textArea.textDocument.modified
onTriggered: textArea.textDocument.save()
}L’ Action e permettant de copier le texte sélectionné n’est activée que si du texte est sélectionné :
Action {
id: copyAction
text: qsTr("&Copy")
shortcut: StandardKey.Copy
enabled: textArea.selectedText
onTriggered: textArea.copy()
}Chaque action permettant de modifier la mise en forme du texte (gras, italique et alignement, par exemple) est une « checkable », et l’état booléen de son « checked » est synchronisé avec la propriété correspondante dans l’« selected text ». La synchronisation bidirectionnelle déclarative étant complexe, nous utilisons un script « onTriggered » pour modifier la propriété lorsque l’action est activée. La propriété ` cursorSelection ` est une nouveauté de Qt 6.7 et facilite considérablement cette opération par rapport à auparavant.
Action {
id: boldAction
text: qsTr("&Bold")
shortcut: StandardKey.Bold
checkable: true
checked: textArea.cursorSelection.font.bold
onTriggered: textArea.cursorSelection.font.bold = checked
}
Action {
id: alignCenterAction
text: qsTr("&Center")
shortcut: "Ctrl+|"
checkable: true
checked: textArea.cursorSelection.alignment === Qt.AlignCenter
onTriggered: textArea.cursorSelection.alignment = Qt.AlignCenter
}Nous disposons d’un fichier « MenuBar » contenant la hiérarchie des objets « Menus » et « MenuItems ». Chaque « MenuItem » doit simplement lier l’objet « action » correspondant, qui encapsule la représentation de l’interface utilisateur et l’implémentation.
menuBar: MenuBar {
Menu {
title: qsTr("&File")
MenuItem {
action: openAction
}
MenuItem {
action: saveAction
}
MenuItem {
action: saveAsAction
}
MenuItem {
action: quitAction
}
}
Menu {
title: qsTr("&Edit")
MenuItem {
action: copyAction
}
...Les mêmes objets ` Action ` sont réutilisés dans l’ ToolBar; mais ici, nous redéfinissons la propriété ` text ` de chaque Action afin de choisir une icône textuelle dans notre police d’icônes :
header: ToolBar {
Flow {
width: parent.width
Row {
id: fileRow
ToolButton {
id: openButton
text: "\uF115" // icon-folder-open-empty
font.family: "fontello"
action: openAction
focusPolicy: Qt.TabFocus
}
ToolButton {
id: saveButton
text: "\uE80A" // icon-floppy-disk
font.family: "fontello"
action: saveAction
focusPolicy: Qt.TabFocus
}
ToolSeparator {
contentItem.visible: fileRow.y === editRow.y
}
}
Row {
id: editRow
ToolButton {
id: copyButton
text: "\uF0C5" // icon-docs
font.family: "fontello"
focusPolicy: Qt.TabFocus
action: copyAction
}
...La partie principale de l’éditeur de texte est un ` TextArea ` situé à l’intérieur d’un ` Flickable` :
Flickable {
id: flickable
flickableDirection: Flickable.VerticalFlick
anchors.fill: parent
ScrollBar.vertical: ScrollBar {}
TextArea.flickable: TextArea {
id: textArea
textFormat: Qt.AutoText
wrapMode: TextArea.Wrap
focus: true
selectByMouse: true
persistentSelection: true
...Un ScrollBar est attaché à l’axe vertical. Le retour à la ligne automatique étant activé via wrapMode, nous n’avons pas besoin d’un ScrollBar horizontal.
La propriété attachée « TextArea.flickable » est utilisée pour que, lorsque le curseur de texte sort de la zone d’affichage (par exemple à l’aide des touches fléchées ou en saisissant beaucoup de texte), « TextArea » fasse défiler la « Flickable » afin de maintenir le curseur visible.
context menu Nous reprenons les mêmes actions que celles déclarées dans les fonctions ` MenuBar ` et ` ToolBar `, puis nous les ajoutons aux éléments existants de la liste de défilement standard fournie par ` TextArea` :
const menu = textArea.ContextMenu.menu
menu.addItem(menuSeparatorComponent.createObject(menu.contentItem))
menu.addAction(fontDialogAction)
menu.addAction(colorDialogAction)Nous utilisons systématiquement la fonction ` qsTr()` pour permettre la traduction du texte de l’interface utilisateur, afin que l’application reste compréhensible quelle que soit la langue maternelle de l’utilisateur final.
Nous utilisons plusieurs types de dialogs:
FileDialog {
id: openDialog
fileMode: FileDialog.OpenFile
selectedNameFilter.index: 1
nameFilters: ["Text files (*.txt)", "HTML files (*.html *.htm)", "Markdown files (*.md *.markdown)"]
currentFolder: StandardPaths.writableLocation(StandardPaths.DocumentsLocation)
onAccepted: {
textArea.textDocument.modified = false // we asked earlier, if necessary
textArea.textDocument.source = selectedFile
}
}
FileDialog {
id: saveDialog
fileMode: FileDialog.SaveFile
nameFilters: openDialog.nameFilters
currentFolder: StandardPaths.writableLocation(StandardPaths.DocumentsLocation)
onAccepted: textArea.textDocument.saveAs(selectedFile)
}
FontDialog {
id: fontDialog
onAccepted: textArea.cursorSelection.font = selectedFont
}
ColorDialog {
id: colorDialog
selectedColor: textArea.cursorSelection.color
onAccepted: textArea.cursorSelection.color = selectedColor
}
MessageDialog {
title: qsTr("Error")
id: errorDialog
}
MessageDialog {
id : quitDialog
title: qsTr("Quit?")
text: qsTr("The file has been modified. Quit anyway?")
buttons: MessageDialog.Yes | MessageDialog.No
onButtonClicked: function (button, role) {
if (role === MessageDialog.YesRole) {
textArea.textDocument.modified = false
Qt.quit()
}
}
}
MessageDialog {
id : discardDialog
title: qsTr("Discard changes?")
text: qsTr("The file has been modified. Open a new file anyway?")
buttons: MessageDialog.Yes | MessageDialog.No
onButtonClicked: function (button, role) {
if (role === MessageDialog.YesRole)
openDialog.open()
}
}Il est généralement plus simple de déclarer des instances distinctes pour chaque usage. Nous disposons de deux instances de ` FileDialog`, respectivement pour l’ouverture et l’enregistrement de fichiers. Cela est devenu plus facile dans Qt 6.7, grâce aux nouvelles fonctionnalités de ` TextDocument`.
Un ` FontDialog ` et un ` ColorDialog ` permettent de modifier la mise en forme du texte. (Au format Markdown, il n’existe pas de syntaxe permettant de spécifier des choix de police et de couleur ; cependant, les caractéristiques de police telles que le gras, l’italique et la police à espacement fixe sont conservées. Au format HTML, toute la mise en forme est conservée.)
Nous disposons d’un « MessageDialog » pour afficher les messages d’erreur, et de deux autres pour indiquer à l’utilisateur la marche à suivre lorsqu’un fichier a été modifié.
Interface utilisateur tactile

L’interface utilisateur tactile est une version simplifiée de l’éditeur de texte. Elle est adaptée aux appareils tactiles dotés d’un écran de taille réduite. L’exemple utilise des sélecteurs de fichiers pour charger automatiquement l’interface utilisateur appropriée.
Exécution de l’exemple
Vous pouvez exécuter l’exemple à partir de :
- Qt Creator
Ouvrez le mode « Welcome » et sélectionnez l'exemple à l'adresse Examples. Pour plus d'informations, consultez Qt Creator: Tutoriel : Compiler et exécuter.
- Qt Extension for Visual Studio Code
Exécutez la commande « Qt: Open Qt examples » à partir de Command Palette, puis sélectionnez l’exemple dans la liste. Pour plus d’informations, consultez Qt Extension for Visual Studio Code: Tutoriel : Compiler et exécuter.
© 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.