構文ハイライトの例
「構文ハイライト」の例では、簡単な構文ハイライトの実装方法を示しています。

構文ハイライトアプリケーションは、C++ ファイルを独自の構文ハイライトで表示します。
このサンプルは 2 つのクラスで構成されています:
Highlighterクラスは、ハイライトルールを定義し、適用します。MainWindowウィジェットは、アプリケーションのメインウィンドウです。
まず、Highlighter クラスを確認し、好みに合わせてQSyntaxHighlighter クラスをカスタマイズする方法を解説します。その後、MainWindow クラスの関連部分を見て、アプリケーションでカスタムハイライトクラスを使用する方法を説明します。
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;
};独自の構文ハイライト機能を提供するには、QSyntaxHighlighter クラスをサブクラス化し、highlightBlock() 関数を再実装し、独自のハイライトルールを定義する必要があります。
ここでは、ハイライトルールをプライベート構造体を使用して格納することにしました。1つのルールは、QRegularExpression パターンとQTextCharFormat インスタンスで構成されます。そして、さまざまなルールはQList を使用して格納されます。
QTextCharFormat クラスは、QTextDocument 内の文字に対する書式設定情報を提供し、テキストの視覚的特性や、ハイパーテキスト文書におけるその役割に関する情報を指定します。この例では、QTextCharFormat::setFontWeight()およびQTextCharFormat::setForeground()関数を使用して、フォントの太さと色のみを定義します。
Highlighterクラスの実装
QSyntaxHighlighter クラスをサブクラス化する際は、基底クラスのコンストラクタに`parent`パラメータを渡す必要があります。`parent`とは、構文ハイライトが適用されるテキストドキュメントのことです。この例では、コンストラクタ内でハイライトルールを定義することにもしました:
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);
}まず、最も一般的な C++ キーワードを認識するキーワードルールを定義します。keywordFormat には、太字の濃い青色のフォントを適用します。各キーワードについて、そのキーワードと指定された書式を HighlightingRule オブジェクトに割り当て、そのオブジェクトをルールリストに追加します。
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);次に、Qtのクラス名に適用するフォーマットを作成します。クラス名は、濃いマゼンタ色で太字として表示されます。 すべての Qt クラス名を捕捉する正規表現である文字列パターンを指定します。次に、その正規表現と指定された書式を HighlightingRule オブジェクトに割り当て、そのオブジェクトをルール一覧に追加します。
また、同じアプローチを用いて、引用文や関数に対するハイライトルールも定義します。パターンは正規表現の形式をとっており、関連する書式設定とともに HighlightingRule オブジェクトに格納されます。
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("\\*/"));
}C++言語には、単一行コメント(// )と複数行コメント(/*...*/ )の2種類のコメントがあります。単一行コメントは、前述のものと同様のハイライトルールを通じて簡単に定義できます。しかし、複数行コメントについては、QSyntaxHighlighter クラスの設計上、特別な注意が必要です。
QSyntaxHighlighter オブジェクトが作成されると、リッチテキストエンジンが必要とするたびにそのhighlightBlock()関数が自動的に呼び出され、指定されたテキストブロックがハイライトされます。問題は、コメントが複数のテキストブロックにまたがっている場合に発生します。 この問題をどのように解決できるかについては、Highlighter::highlightBlock() 関数の実装を検討する際に詳しく見ていきます。現時点では、複数行にわたるコメントの色を指定するのみとします。
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);
}
}highlightBlock() 関数は、リッチテキストエンジンが必要と判断したとき、つまり変更されたテキストブロックが存在する場合に、自動的に呼び出されます。
まず、highlightingRules リストに保存された構文ハイライトルールを適用します。各ルール(つまり、各HighlightingRuleオブジェクト)について、QString::indexOf()関数を使用して、指定されたテキストブロック内でパターンを検索します。 パターンの最初の出現箇所が見つかったら、QRegularExpressionMatch::capturedLength() 関数を使用して、書式設定の対象となる文字列を特定します。QRegularExpressionMatch::capturedLength() は、最後に一致した文字列の長さを返し、一致する文字列がない場合は 0 を返します。
実際の書式設定を行うために、QSyntaxHighlighter クラスはsetFormat()関数を提供しています。この関数は、highlightBlock() 関数の引数として渡されたテキストブロックに対して動作します。 指定された書式は、指定された開始位置から指定された長さ分だけテキストに適用されます。指定された書式で設定された書式設定プロパティは、表示時にドキュメントに直接保存されている書式設定情報と統合されます。なお、この関数を通じて設定された書式によって、ドキュメント自体が変更されることはありません。
この処理は、現在のテキストブロック内でパターンが最後に現れる箇所が見つかるまで繰り返されます。
setCurrentBlockState(0);複数のテキストブロックにまたがる構造(C++ の複数行コメントなど)を扱うには、前のテキストブロックの終了状態(例:「コメント内」)を知る必要があります。highlightBlock() の実装内では、QSyntaxHighlighter::previousBlockState()関数を使用して、直前のテキストブロックの終了状態を照会できます。ブロックの解析後、QSyntaxHighlighter::setCurrentBlockState()を使用して最後の状態を保存できます。
previousBlockState() 関数は int 型の値を返します。状態が設定されていない場合、戻り値は -1 になります。setCurrentBlockState() 関数を使用して、任意の状態を識別するために任意の値を指定できます。状態が設定されると、QTextBlock は、その値が再度設定されるか、対応するテキスト段落が削除されるまで、その値を保持します。
この例では、「コメント外」の状態を 0、「コメント内」の状態を 1 で表すことにしました。保存された構文強調表示ルールが適用されると、現在のブロック状態を 0 に初期化します。
int startIndex = 0;
if (previousBlockState() != 1)
startIndex = text.indexOf(commentStartExpression);前のブロック状態が「コメント内」(previousBlockState() == 1 )だった場合、テキストブロックの先頭から終了式(end expression)の検索を開始します。previousBlockState()が0を返した場合は、開始式(start expression)が最初に現れる位置から検索を開始します。
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);
}
}終了式が見つかったら、コメントの長さを計算し、複数行コメントのフォーマットを適用します。その後、開始式の次の出現箇所を検索し、この処理を繰り返します。現在のテキストブロック内で終了式が見つからない場合は、現在のブロック状態を1、つまり「in comment」に設定します。
これでHighlighter クラスの実装は完了し、使用可能な状態になりました。
MainWindowクラスの定義
QSyntaxHighlighter のサブクラスの使用方法は簡単です。アプリケーションにこのクラスのインスタンスを用意し、ハイライト処理を適用したいドキュメントを渡すだけです。
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;
};この例では、Highlighter インスタンスへのポインタを宣言し、後でprivate関数setupEditor() 内で初期化します。
MainWindowクラスの実装
メインウィンドウのコンストラクタは単純明快です。まずメニューを設定し、次にエディタを初期化して、アプリケーションの中心となるウィジェットに設定します。最後に、メインウィンドウのタイトルを設定します。
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setupFileMenu();
setupHelpMenu();
setupEditor();
setCentralWidget(editor);
setWindowTitle(tr("Syntax Highlighter"));
}Highlighter オブジェクトの初期化と配置は、プライベートな便利関数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());
}まず、エディタで使用したいフォントを作成し、次にQTextEdit クラスのインスタンスであるエディタ自体を作成します。MainWindow クラスの定義ファイルを使用してエディタを初期化する前に、エディタのドキュメントを引数として渡してHighlighter のインスタンスを作成します。これが、ハイライト処理が適用されるドキュメントです。これで完了です。
QSyntaxHighlighter オブジェクトは、一度に1つのドキュメントにのみインストールできますが、QSyntaxHighlighter::setDocument()関数を使用すれば、別のドキュメントにハイライト機能を簡単に再インストールできます。また、QSyntaxHighlighter クラスには、現在設定されているドキュメントを返すdocument()関数も用意されています。
© 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.