Qt Quick Contrôles - Éditeur de texte
Une application d'éditeur de texte riche utilisant Qt Quick Controls.
L'exemple de l'éditeur de texte permet l'édition WYSIWYG d'un fichier HTML, Markdown ou texte brut. L'application est livrée avec deux interfaces utilisateur : une pour les grands écrans et une autre simplifiée pour les petits appareils tactiles. Les deux sont en QML "pur". 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 qui permet de formater le texte et d'ouvrir et d'enregistrer des fichiers HTML, Markdown et de texte brut.
Dans le modèle de conception modèle-vue-contrôle (MVC), la couche de contrôle comprend l'ensemble des opérations qui peuvent être effectuées. Dans les contrôles Qt Quick, le type Action est utilisé pour encapsuler une opération ou une commande unique. En conséquence, 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() } }
L'objet Action pour l'ouverture d'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. Dans le cas contraire, il ouvre simplement l'objet FileDialog qui est déclaré plus loin.
La fonction 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() }
La fonction Action de copie du 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 le formatage du texte (gras, italique et alignement) est checkable, et son état booléen checked est synchronisé avec la propriété correspondante dans selected text. La synchronisation bidirectionnelle déclarative étant difficile, nous utilisons un script onTriggered pour modifier la propriété lorsque l'action est activée. La propriété cursorSelection est nouvelle dans Qt 6.7 et rend cela beaucoup plus facile qu'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 avons un MenuBar qui contient la hiérarchie des Menus et des MenuItems. Chaque MenuItem doit simplement lier le 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 ToolBar; mais ici, nous surchargeons la propriété text de chaque action pour choisir une icône textuelle à partir de 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 à 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. Étant donné que l'habillage des mots est activé via wrapMode, nous n'avons pas besoin d'un ScrollBar horizontal.
La propriété TextArea.flickable attached est utilisée pour que, lorsque le curseur de texte est déplacé hors de la fenêtre de visualisation (par exemple à l'aide des touches fléchées ou en tapant beaucoup de texte), TextArea fasse défiler Flickable pour que le curseur reste visible.
Nous prenons les mêmes actions que nous avons déclarées dans MenuBar et ToolBar et les ajoutons aux éléments existants dans la norme context menu 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 ait un sens 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 facile de déclarer des instances distinctes pour chaque usage. Nous avons deux instances de FileDialog, pour l'ouverture et l'enregistrement de fichiers respectivement. Cela est devenu plus facile dans Qt 6.7, avec les nouvelles fonctionnalités de TextDocument.
Un FontDialog et un ColorDialog permettent de modifier le formatage du texte. (Au format Markdown, il n'y a pas de syntaxe pour représenter des choix spécifiques de polices et de couleurs ; mais les caractéristiques des polices telles que gras, italique et monospace sont sauvegardées. Au format HTML, toutes les mises en forme sont sauvegardées).
Nous disposons d'une page MessageDialog pour afficher les messages d'erreur et de deux autres pour indiquer à l'utilisateur ce qu'il doit faire lorsqu'un fichier a été modifié.
Interface utilisateur tactile

L'interface utilisateur tactile est une version simplifiée de l'éditeur de texte. Elle convient aux appareils tactiles dont la taille de l'écran est limitée. L'exemple utilise des sélecteurs de fichiers pour charger automatiquement l'interface utilisateur appropriée.
Exécution de l'exemple
Pour exécuter l'exemple à partir de Qt Creatorouvrez le mode Welcome et sélectionnez l'exemple à partir de Examples. Pour plus d'informations, voir Qt Creator: Tutoriel : Construire 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.