Sur cette page

L'interface QTextCursor

Les documents peuvent être modifiés via l’interface fournie par la classe ` QTextCursor ` ; les curseurs sont soit créés à l’aide d’un constructeur, soit obtenus à partir d’un widget d’édition. Le curseur sert à effectuer des opérations d’édition qui correspondent exactement à celles que l’utilisateur peut effectuer lui-même dans un éditeur. De ce fait, des informations sur la structure du document sont également disponibles via le curseur, ce qui permet de modifier cette structure. L’utilisation d’une interface d’édition orientée curseur simplifie le processus de création d’un éditeur personnalisé pour les développeurs, car les opérations d’édition peuvent être facilement visualisées.

La classe ` QTextCursor ` conserve également des informations sur tout texte qu’elle a sélectionné dans le document, en suivant là encore un modèle conceptuellement similaire aux actions effectuées par l’utilisateur pour sélectionner du texte dans un éditeur.

Les documents en texte enrichi peuvent être associés à plusieurs curseurs, et chacun d’entre eux contient des informations sur sa position dans le document et sur les sélections qu’il peut contenir. Ce paradigme basé sur le curseur facilite la mise en œuvre par programmation d’opérations courantes, telles que le copier-coller de texte, tout en permettant d’effectuer des opérations d’édition plus complexes sur le document.

Ce chapitre décrit la plupart des opérations d’édition courantes que vous devrez effectuer à l’aide d’un curseur, depuis l’insertion de base de texte et d’éléments de document jusqu’à la manipulation plus complexe des structures de document.

Édition basée sur les curseurs

À leur niveau le plus simple, les documents texte sont constitués d’une chaîne de caractères, balisée d’une certaine manière pour représenter la structure en blocs du texte au sein du document. L’ QTextCursor fournit une interface basée sur le curseur qui permet de manipuler le contenu d’un QTextDocument au niveau des caractères. Comme les éléments (blocs, cadres, tableaux, etc.) sont également encodés dans le flux de caractères, la structure du document peut elle-même être modifiée à l’aide du curseur.

Le curseur garde la trace de sa position au sein du document parent et peut fournir des informations sur la structure environnante, telle que le bloc de texte, le cadre, le tableau ou la liste qui l’entoure. Les formats des structures environnantes peuvent également être obtenus directement via le curseur.

Utilisation d’un curseur

Le curseur sert principalement à insérer ou à modifier du texte au sein d’un bloc. Pour ce faire, on peut utiliser le curseur d’un éditeur de texte :

    QTextEdit *editor = new QTextEdit();
    QTextCursor cursor(editor->textCursor());

Sinon, on peut obtenir un curseur directement à partir d’un document :

    QTextDocument *document = new QTextDocument(editor);
    QTextCursor cursor(document);

Le curseur est positionné au début du document, ce qui permet d’écrire dans le premier bloc (vide) du document.

Regroupement des opérations du curseur

Une série d’opérations d’édition peut être regroupée afin de pouvoir être reproduite ou annulée en une seule fois. Pour ce faire, on utilise les fonctions ` beginEditBlock() ` et ` endEditBlock() ` de la manière suivante, comme dans l’exemple ci-dessous où l’on sélectionne le mot contenant le curseur :

    cursor.beginEditBlock();
    cursor.movePosition(QTextCursor::StartOfWord);
    cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
    cursor.endEditBlock();

Si les opérations d'édition ne sont pas regroupées, le document enregistre automatiquement chacune d'entre elles individuellement afin qu'elles puissent être annulées ultérieurement. Le regroupement des opérations en ensembles plus importants peut rendre l'édition plus efficace tant pour l'utilisateur que pour l'application, mais il faut veiller à ne pas regrouper un trop grand nombre d'opérations, car l'utilisateur peut souhaiter exercer un contrôle plus fin sur le processus d'annulation.

Curseurs multiples

Il est possible d’utiliser plusieurs curseurs pour éditer simultanément le même document, bien qu’un seul soit visible pour l’utilisateur dans un widget « QTextEdit ». L’ QTextDocument veille à ce que chaque curseur écrive correctement le texte et n’interfère avec aucun des autres.

Insertion d’éléments de document

QTextCursor fournit plusieurs fonctions permettant de modifier la structure d’un document de texte enrichi. En général, ces fonctions permettent de créer des éléments de document avec les informations de mise en forme appropriées, et ceux-ci sont insérés dans le document à la position du curseur.

Le premier groupe de fonctions insère des éléments de niveau bloc et met à jour la position du curseur, mais ne renvoie pas l’élément qui a été inséré :

  • insertBlock() insère un nouveau bloc de texte (paragraphe) dans un document à la position du curseur, puis déplace le curseur au début du nouveau bloc.
  • insertFragment() insère un fragment de texte existant dans un document à la position du curseur.
  • insertImage() insère une image dans un document à la position du curseur.
  • insertText() insère du texte dans le document à la position du curseur.

Vous pouvez examiner le contenu de l’élément qui a été inséré via l’interface du curseur.

Le deuxième groupe de fonctions insère des éléments qui structurent le document et renvoie la structure qui a été insérée :

  • insertFrame() insère un cadre dans le document après le bloc actuel du curseur, puis déplace le curseur au début du bloc vide du nouveau cadre.
  • insertList() insère une liste dans le document à la position du curseur, puis déplace le curseur au début du premier élément de la liste.
  • insertTable() insère un tableau dans le document après le bloc actuel du curseur, puis déplace le curseur au début du bloc suivant le tableau.

Ces éléments contiennent ou regroupent d’autres éléments du document.

Texte et fragments de texte

Le texte peut être inséré dans le bloc actuel selon le format de caractère actuel, ou selon un format personnalisé spécifié avec le texte :

    cursor.insertText(tr("Character formats"),
                      headingFormat);

    cursor.insertBlock();

    cursor.insertText(tr("Text can be displayed in a variety of "
                                  "different character formats. "), plainFormat);
    cursor.insertText(tr("We can emphasize text by "));
    cursor.insertText(tr("making it italic"), emphasisFormat);

Une fois qu’un format de caractères a été utilisé avec un curseur, ce format devient le format par défaut pour tout texte inséré avec ce curseur jusqu’à ce qu’un autre format de caractères soit spécifié.

Si un curseur est utilisé pour insérer du texte sans spécifier de format de caractères, le texte se verra attribuer le format de caractères utilisé à cette position dans le document.

Blocs

Les blocs de texte sont insérés dans le document à l'aide de la fonction insertBlock().

    QTextBlockFormat backgroundFormat = blockFormat;
    backgroundFormat.setBackground(QColor("lightGray"));

    cursor.setBlockFormat(backgroundFormat);

Le curseur est positionné au début du nouveau bloc.

Cadres

Les cadres sont insérés dans un document à l'aide du curseur et seront placés dans le cadre actuel du curseur, après le bloc en cours. Le code suivant montre comment insérer un cadre entre deux blocs de texte dans le cadre racine d’un document. Nous commençons par déterminer le cadre actuel du curseur :

    QTextFrame *mainFrame = cursor.currentFrame();
    cursor.insertText(...);

Nous insérons du texte dans ce cadre, puis nous définissons un format de cadre pour le cadre enfant :

    QTextFrameFormat frameFormat;
    frameFormat.setMargin(32);
    frameFormat.setPadding(8);
    frameFormat.setBorder(4);

Ce format de cadre confère au cadre une marge externe de 32 pixels, un remplissage interne de 8 pixels et une bordure de 4 pixels de large. Consultez la documentation d’ QTextFrameFormat pour plus d’informations sur les formats de cadres.

Le cadre est inséré dans le document après le texte précédent :

    cursor.insertFrame(frameFormat);
    cursor.insertText(...);

Nous ajoutons du texte au document immédiatement après avoir inséré le cadre. Comme le curseur texte est positionné à l'intérieur du cadre lorsqu'il est inséré dans le document, ce texte sera également inséré à l'intérieur du cadre.

Enfin, nous positionnons le curseur à l’extérieur du cadre en reprenant la dernière position disponible du curseur à l’intérieur du cadre que nous avons enregistrée précédemment :

    cursor = mainFrame->lastCursorPosition();
    cursor.insertText(...);

Le texte que nous ajoutons en dernier est inséré après le cadre enfant dans le document. Chaque cadre étant rempli de blocs de texte, cela garantit qu’il est toujours possible d’insérer davantage d’éléments à l’aide du curseur.

Tableaux

Les tableaux sont insérés dans le document à l’aide du curseur et seront placés dans le cadre actuel du curseur, après le bloc en cours :

    QTextCursor cursor(editor->textCursor());
    QTextTable *table = cursor.insertTable(rows, columns, tableFormat);

Les tableaux peuvent être créés avec un format spécifique qui définit leurs propriétés globales, telles que leur alignement, leur couleur d’arrière-plan et l’espacement des cellules utilisé. Ce format peut également déterminer les contraintes applicables à chaque colonne, permettant à chacune d’avoir une largeur fixe ou de s’adapter à l’espace disponible.

    QTextTableFormat tableFormat;
    tableFormat.setBackground(QColor("#e0e0e0"));
    QList<QTextLength> constraints;
    constraints << QTextLength(QTextLength::PercentageLength, 16);
    constraints << QTextLength(QTextLength::PercentageLength, 28);
    constraints << QTextLength(QTextLength::PercentageLength, 28);
    constraints << QTextLength(QTextLength::PercentageLength, 28);
    tableFormat.setColumnWidthConstraints(constraints);
    QTextTable *table = cursor.insertTable(rows, columns, tableFormat);

Les colonnes du tableau créé ci-dessus occuperont chacune un certain pourcentage de la largeur disponible. Notez que le format du tableau est facultatif ; si vous insérez un tableau sans format, des valeurs par défaut pertinentes seront utilisées pour les propriétés du tableau.

Comme les cellules peuvent contenir d’autres éléments du document, elles peuvent elles aussi être mises en forme et stylisées selon les besoins.

Il est possible d’ajouter du texte au tableau en se positionnant sur chaque cellule avec le curseur et en saisissant du texte.

    cell = table->cellAt(0, 0);
    cellCursor = cell.firstCursorPosition();
    cellCursor.insertText(tr("Week"), charFormat);

Nous pouvons créer un emploi du temps simple en suivant cette approche :

    for (column = 1; column < columns; ++column) {
        cell = table->cellAt(0, column);
        cellCursor = cell.firstCursorPosition();
        cellCursor.insertText(tr("Team %1").arg(column), charFormat);
    }

    for (row = 1; row < rows; ++row) {
        cell = table->cellAt(row, 0);
        cellCursor = cell.firstCursorPosition();
        cellCursor.insertText(tr("%1").arg(row), charFormat);

        for (column = 1; column < columns; ++column) {
            if ((row-1) % 3 == column-1) {
                cell = table->cellAt(row, column);
                QTextCursor cellCursor = cell.firstCursorPosition();
                cellCursor.insertText(tr("On duty"), charFormat);
            }
        }
    }

Listes

Des listes d’éléments en bloc peuvent être créées automatiquement et insérées dans le document à la position actuelle du curseur. Chaque liste ainsi créée nécessite la spécification d’un format de liste :

    QTextListFormat listFormat;
    if (list) {
        listFormat = list->format();
        listFormat.setIndent(listFormat.indent() + 1);
    }

    listFormat.setStyle(QTextListFormat::ListDisc);
    cursor.insertList(listFormat);

Le code ci-dessus vérifie d’abord si le curseur se trouve au sein d’une liste existante et, si c’est le cas, attribue au format de liste de la nouvelle liste un niveau d’indentation approprié. Cela permet de créer des listes imbriquées avec des niveaux d’indentation croissants. Une implémentation plus sophistiquée utiliserait également différents types de symboles pour les puces à chaque niveau de la liste.

Images

Les images en ligne sont ajoutées aux documents via le curseur de la manière habituelle. Contrairement à de nombreux autres éléments, toutes les propriétés d'une image sont spécifiées par le format de l'image. Cela signifie qu'un objet ` QTextImageFormat ` doit être créé avant de pouvoir insérer une image :

    QTextImageFormat imageFormat;
    imageFormat.setName(":/images/advert.png");
    cursor.insertImage(imageFormat);

Le nom de l’image fait référence à une entrée du fichier de ressources de l’application. La méthode utilisée pour dériver ce nom est décrite dans la section « Le système de ressources Qt ».

Exemples

Le texte enrichi est stocké dans des documents texte qui peuvent être créés soit en important du code HTML depuis une source externe, soit en utilisant un objet ` QTextCursor`.

Manipulation du texte enrichi

La manière la plus simple d’utiliser un document de texte enrichi consiste à utiliser la classe ` QTextEdit `, qui fournit une vue modifiable du document. Le code ci-dessous importe du code HTML dans un document et affiche ce dernier à l’aide d’un widget d’édition de texte.

QTextEdit *editor = new QTextEdit(parent);
editor->setHtml(aStringContainingHTMLtext);
editor->show();

Vous pouvez récupérer le document à partir de la zone d’édition de texte à l’aide de la fonction document(). Le document peut ensuite être modifié par programmation à l’aide de la classe ` QTextCursor `. Cette classe s’inspire d’un curseur d’écran, et les opérations d’édition suivent la même sémantique. Le code suivant met la première ligne du document en gras, sans modifier les autres propriétés de police. L'éditeur sera automatiquement mis à jour pour refléter les modifications apportées aux données du document sous-jacent.

QTextDocument *document = edit->document();
QTextCursor cursor(document);

cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);

QTextCharFormat format;
format.setFontWeight(QFont::Bold);

cursor.mergeCharFormat(format);

Notez que le curseur a été déplacé du début de la première ligne vers la fin, tout en conservant un point d'ancrage au début de la ligne. Cela illustre les fonctionnalités de sélection basées sur le curseur de la classe ` QTextCursor `.

Génération d’un calendrier

Le texte enrichi peut être généré très rapidement à l’aide de l’approche basée sur le curseur. L’exemple suivant présente un calendrier simple dans un widget ` QTextEdit ` avec des en-têtes en gras pour les jours de la semaine :

    editor = new QTextEdit(this);

    QTextCursor cursor(editor->textCursor());
    cursor.movePosition(QTextCursor::Start);

    QTextCharFormat format(cursor.charFormat());
    format.setFontFamilies({"Courier"});

    QTextCharFormat boldFormat = format;
    boldFormat.setFontWeight(QFont::Bold);

    cursor.insertBlock();
    cursor.insertText(" ", boldFormat);

    QDate date = QDate::currentDate();
    int year = date.year(), month = date.month();

    for (int weekDay = 1; weekDay <= 7; ++weekDay) {
        cursor.insertText(QString("%1 ").arg(QLocale::system().dayName(weekDay), 3),
            boldFormat);
    }

    cursor.insertBlock();
    cursor.insertText(" ", format);

    for (int column = 1; column < QDate(year, month, 1).dayOfWeek(); ++column) {
        cursor.insertText("    ", format);
    }

    for (int day = 1; day <= date.daysInMonth(); ++day) {
        int weekDay = QDate(year, month, day).dayOfWeek();

        if (QDate(year, month, day) == date)
            cursor.insertText(QString("%1 ").arg(day, 3), boldFormat);
        else
            cursor.insertText(QString("%1 ").arg(day, 3), format);

        if (weekDay == 7) {
            cursor.insertBlock();
            cursor.insertText(" ", format);
        }
    }

L’exemple ci-dessus montre à quel point il est simple de générer rapidement de nouveaux documents en texte enrichi à l’aide d’un minimum de code. Bien que nous ayons généré un calendrier rudimentaire à espacement fixe pour éviter de citer trop de code, Scribe offre des fonctionnalités de mise en page et de formatage bien plus sophistiquées.

© 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.