Exemple de surlignage de syntaxe
L'exemple « Mise en évidence de la syntaxe » montre comment effectuer une mise en évidence simple de la syntaxe.

L'application « Syntax Highlighter » affiche des fichiers C++ avec une mise en évidence de la syntaxe personnalisée.
L'exemple se compose de deux classes :
- La classe «
Highlighter» définit et applique les règles de mise en évidence. - Le widget «
MainWindow» correspond à la fenêtre principale de l'application.
Nous allons d’abord passer en revue la classe « Highlighter » pour voir comment vous pouvez personnaliser la classe « QSyntaxHighlighter » en fonction de vos préférences, puis nous examinerons les parties pertinentes de la classe « MainWindow » pour voir comment vous pouvez utiliser votre classe de mise en évidence personnalisée dans une application.
Définition de la classe Highlighter
class Highlighter : public QSyntaxHighlighter
{
Q_OBJECT
public:
Highlighter(QTextDocument *parent = nullptr);
protected:
void highlightBlock(const QString &text) override;
private:
struct HighlightingRule
{
QRegularExpression pattern;
QTextCharFormat format;
};
QList<HighlightingRule> highlightingRules;
QRegularExpression commentStartExpression;
QRegularExpression commentEndExpression;
QTextCharFormat keywordFormat;
QTextCharFormat classFormat;
QTextCharFormat singleLineCommentFormat;
QTextCharFormat multiLineCommentFormat;
QTextCharFormat quotationFormat;
QTextCharFormat functionFormat;
};Pour proposer votre propre mise en évidence syntaxique, vous devez créer une sous-classe de ` QSyntaxHighlighter`, réimplémenter la fonction ` highlightBlock()` et définir vos propres règles de mise en évidence.
Nous avons choisi de stocker nos règles de mise en évidence à l’aide d’une structure privée : une règle se compose d’un motif ` QRegularExpression ` et d’une instance ` QTextCharFormat `. Les différentes règles sont ensuite stockées à l’aide d’un ` QList`.
La classe QTextCharFormat fournit des informations de mise en forme pour les caractères d’un QTextDocument, en spécifiant les propriétés visuelles du texte ainsi que des informations sur son rôle dans un document hypertexte. Dans cet exemple, nous ne définirons que l’épaisseur et la couleur de la police à l’aide des fonctions QTextCharFormat::setFontWeight() et QTextCharFormat::setForeground().
Implémentation de la classe Highlighter
Lors de la création d’une sous-classe de la classe QSyntaxHighlighter, vous devez transmettre le paramètre parent au constructeur de la classe de base. Le parent est le document texte auquel la mise en évidence syntaxique sera appliquée. Dans cet exemple, nous avons également choisi de définir nos règles de mise en évidence dans le constructeur :
Highlighter::Highlighter(QTextDocument *parent)
: QSyntaxHighlighter(parent)
{
HighlightingRule rule;
keywordFormat.setForeground(Qt::darkBlue);
keywordFormat.setFontWeight(QFont::Bold);
const QString keywordPatterns[] = {
QStringLiteral("\\bchar\\b"), QStringLiteral("\\bclass\\b"), QStringLiteral("\\bconst\\b"),
QStringLiteral("\\bdouble\\b"), QStringLiteral("\\benum\\b"), QStringLiteral("\\bexplicit\\b"),
QStringLiteral("\\bfriend\\b"), QStringLiteral("\\binline\\b"), QStringLiteral("\\bint\\b"),
QStringLiteral("\\blong\\b"), QStringLiteral("\\bnamespace\\b"), QStringLiteral("\\boperator\\b"),
QStringLiteral("\\bprivate\\b"), QStringLiteral("\\bprotected\\b"), QStringLiteral("\\bpublic\\b"),
QStringLiteral("\\bshort\\b"), QStringLiteral("\\bsignals\\b"), QStringLiteral("\\bsigned\\b"),
QStringLiteral("\\bslots\\b"), QStringLiteral("\\bstatic\\b"), QStringLiteral("\\bstruct\\b"),
QStringLiteral("\\btemplate\\b"), QStringLiteral("\\btypedef\\b"), QStringLiteral("\\btypename\\b"),
QStringLiteral("\\bunion\\b"), QStringLiteral("\\bunsigned\\b"), QStringLiteral("\\bvirtual\\b"),
QStringLiteral("\\bvoid\\b"), QStringLiteral("\\bvolatile\\b"), QStringLiteral("\\bbool\\b")
};
for (const QString &pattern : keywordPatterns) {
rule.pattern = QRegularExpression(pattern);
rule.format = keywordFormat;
highlightingRules.append(rule);
}keywordFormat Nous définissons tout d’abord une règle de mots-clés qui reconnaît les mots-clés C++ les plus courants. Nous attribuons aux mots-clés une police en gras et de couleur bleu foncé. Pour chaque mot-clé, nous assignons le mot-clé et le format spécifié à un objet `HighlightingRule`, puis nous ajoutons cet objet à notre liste de règles.
classFormat.setFontWeight(QFont::Bold);
classFormat.setForeground(Qt::darkMagenta);
rule.pattern = QRegularExpression(QStringLiteral("\\bQ[A-Za-z]+\\b"));
rule.format = classFormat;
highlightingRules.append(rule);
quotationFormat.setForeground(Qt::darkGreen);
rule.pattern = QRegularExpression(QStringLiteral("\".*\""));
rule.format = quotationFormat;
highlightingRules.append(rule);
functionFormat.setFontItalic(true);
functionFormat.setForeground(Qt::blue);
rule.pattern = QRegularExpression(QStringLiteral("\\b[A-Za-z0-9_]+(?=\\()"));
rule.format = functionFormat;
highlightingRules.append(rule);Ensuite, nous créons un format que nous appliquerons aux noms de classes Qt. Les noms de classes seront affichés en magenta foncé et en gras. Nous spécifions un motif de chaîne qui est en réalité une expression régulière capturant tous les noms de classes Qt. Ensuite, nous attribuons l’expression régulière et le format spécifié à un objet `HighlightingRule`, puis nous ajoutons cet objet à notre liste de règles.
Nous définissons également des règles de mise en évidence pour les citations et les fonctions en utilisant la même approche : les modèles se présentent sous la forme d’expressions régulières et sont stockés dans des objets `HighlightingRule` avec le format associé.
singleLineCommentFormat.setForeground(Qt::red);
rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*"));
rule.format = singleLineCommentFormat;
highlightingRules.append(rule);
multiLineCommentFormat.setForeground(Qt::red);
commentStartExpression = QRegularExpression(QStringLiteral("/\\*"));
commentEndExpression = QRegularExpression(QStringLiteral("\\*/"));
}Le langage C++ propose deux types de commentaires : le commentaire sur une seule ligne (//) et le commentaire sur plusieurs lignes (/*...*/ ). Le commentaire sur une seule ligne peut facilement être défini à l’aide d’une règle de mise en évidence similaire aux précédentes. En revanche, le commentaire sur plusieurs lignes nécessite une attention particulière en raison de la conception de la classe ` QSyntaxHighlighter `.
Une fois l’objet ` QSyntaxHighlighter ` créé, sa fonction ` highlightBlock()` est appelée automatiquement chaque fois que le moteur de texte enrichi en a besoin, ce qui met en surbrillance le bloc de texte concerné. Le problème survient lorsqu’un commentaire s’étend sur plusieurs blocs de texte. Nous examinerons de plus près comment résoudre ce problème lors de l’étude de l’implémentation de la fonction ` Highlighter::highlightBlock() `. Pour l’instant, nous nous contentons de spécifier la couleur du commentaire multiligne.
void Highlighter::highlightBlock(const QString &text)
{
for (const HighlightingRule &rule : std::as_const(highlightingRules)) {
QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text);
while (matchIterator.hasNext()) {
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
}
}La fonction `highlightBlock()` est appelée automatiquement chaque fois que le moteur de texte enrichi le juge nécessaire, c'est-à-dire lorsqu'il y a des blocs de texte qui ont été modifiés.
Nous appliquons d’abord les règles de mise en évidence syntaxique que nous avons stockées dans la liste ` highlightingRules `. Pour chaque règle (c’est-à-dire pour chaque objet `HighlightingRule`), nous recherchons le motif dans le bloc de texte donné à l’aide de la fonction ` QString::indexOf()`. Lorsque la première occurrence du motif est trouvée, nous utilisons la fonction ` QRegularExpressionMatch::capturedLength()` pour déterminer la chaîne qui sera mise en forme. La fonction ` QRegularExpressionMatch::capturedLength()` renvoie la longueur de la dernière chaîne correspondante, ou 0 s’il n’y a pas eu de correspondance.
Pour effectuer le formatage proprement dit, la classe ` QSyntaxHighlighter ` fournit la fonction ` setFormat()`. Cette fonction opère sur le bloc de texte transmis en argument à la fonction ` highlightBlock() ()`. Le format spécifié est appliqué au texte à partir de la position de départ indiquée et sur la longueur spécifiée. Les propriétés de mise en forme définies dans le format donné sont fusionnées au moment de l’affichage avec les informations de mise en forme stockées directement dans le document. Notez que le document lui-même n’est pas modifié par le format défini via cette fonction.
Ce processus est répété jusqu’à ce que la dernière occurrence du motif dans le bloc de texte actuel soit trouvée.
setCurrentBlockState(0);Pour gérer les constructions pouvant s’étendre sur plusieurs blocs de texte (comme les commentaires multilignes en C++), il est nécessaire de connaître l’état final du bloc de texte précédent (par exemple « dans un commentaire »). Au sein de votre implémentation de ` highlightBlock() `, vous pouvez interroger l'état de fin du bloc de texte précédent à l'aide de la fonction ` QSyntaxHighlighter::previousBlockState()`. Après avoir analysé le bloc, vous pouvez enregistrer le dernier état à l'aide de ` QSyntaxHighlighter::setCurrentBlockState()`.
La fonction ` previousBlockState()` renvoie une valeur de type `int`. Si aucun état n’est défini, la valeur renvoyée est -1. Vous pouvez attribuer n’importe quelle autre valeur pour identifier un état donné à l’aide de la fonction ` setCurrentBlockState()`. Une fois l’état défini, la variable ` QTextBlock ` conserve cette valeur jusqu’à ce qu’elle soit redéfinie ou jusqu’à ce que le paragraphe de texte correspondant soit supprimé.
Dans cet exemple, nous avons choisi d'utiliser 0 pour représenter l'état « pas en commentaire » et 1 pour l'état « en commentaire ». Lorsque les règles de mise en évidence syntaxique enregistrées sont appliquées, nous initialisons l'état du bloc actuel à 0.
int startIndex = 0;
if (previousBlockState() != 1)
startIndex = text.indexOf(commentStartExpression);Si l'état du bloc précédent était « dans un commentaire » (previousBlockState() == 1), nous commençons la recherche d’une expression de fin au début du bloc de texte. Si la fonction previousBlockState() renvoie 0, nous commençons la recherche à l’emplacement de la première occurrence d’une expression de début.
while (startIndex >= 0) {
QRegularExpressionMatch match = commentEndExpression.match(text, startIndex);
int endIndex = match.capturedStart();
int commentLength = 0;
if (endIndex == -1) {
setCurrentBlockState(1);
commentLength = text.length() - startIndex;
} else {
commentLength = endIndex - startIndex
+ match.capturedLength();
}
setFormat(startIndex, commentLength, multiLineCommentFormat);
startIndex = text.indexOf(commentStartExpression, startIndex + commentLength);
}
}Lorsqu’une expression de fin est trouvée, nous calculons la longueur du commentaire et appliquons le format de commentaire multiligne. Ensuite, nous recherchons la prochaine occurrence de l’expression de début et répétons le processus. Si aucune expression de fin ne peut être trouvée dans le bloc de texte actuel, nous définissons l’état du bloc actuel sur 1, c’est-à-dire « dans un commentaire ».
L’implémentation de la classe ` Highlighter ` est ainsi terminée ; elle est désormais prête à l’emploi.
Définition de la classe MainWindow
L’utilisation d’une sous-classe de ` QSyntaxHighlighter ` est simple : il suffit de fournir à votre application une instance de la classe et de lui transmettre le document sur lequel vous souhaitez appliquer la mise en évidence.
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
public slots:
void about();
void newFile();
void openFile(const QString &path = QString());
private:
void setupEditor();
void setupFileMenu();
void setupHelpMenu();
QTextEdit *editor;
Highlighter *highlighter;
};Dans cet exemple, nous déclarons un pointeur vers une instance de ` Highlighter ` que nous initialiserons ultérieurement dans la fonction privée ` setupEditor() `.
Implémentation de la classe MainWindow
Le constructeur de la fenêtre principale est très simple. Nous configurons d’abord les menus, puis nous initialisons l’éditeur et en faisons le widget central de l’application. Enfin, nous définissons le titre de la fenêtre principale.
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setupFileMenu();
setupHelpMenu();
setupEditor();
setCentralWidget(editor);
setWindowTitle(tr("Syntax Highlighter"));
}Nous initialisons et installons l’objet ` Highlighter ` dans la fonction d’aide privée `setupEditor()` :
void MainWindow::setupEditor()
{
QFont font;
font.setFamily("Courier");
font.setFixedPitch(true);
font.setPointSize(10);
editor = new QTextEdit;
editor->setFont(font);
highlighter = new Highlighter(editor->document());
QFile file("mainwindow.h");
if (file.open(QFile::ReadOnly | QFile::Text))
editor->setPlainText(file.readAll());
}Nous créons d’abord la police que nous souhaitons utiliser dans l’éditeur, puis nous créons l’éditeur lui-même, qui est une instance de la classe ` QTextEdit `. Avant d’initialiser l’éditeur à l’aide du fichier de définition de classe ` MainWindow `, nous créons une instance de ` Highlighter ` en lui passant le document de l’éditeur comme argument. Il s’agit du document auquel la mise en évidence sera appliquée. Nous avons alors terminé.
Un objet QSyntaxHighlighter ne peut être installé que sur un seul document à la fois, mais vous pouvez facilement réinstaller le surligneur sur un autre document à l'aide de la fonction QSyntaxHighlighter::setDocument(). La classe QSyntaxHighlighter fournit également la fonction document() qui renvoie le document actuellement défini.
© 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.