このページでは

リッチテキスト文書の構造

テキスト文書はQTextDocument クラスによって表現されます。このクラスは、文書の内部表現や構造に関する情報を保持し、元に戻す/やり直し機能を提供するために変更履歴を追跡します。

テキスト文書の構造化された表現では、その内容がテキストブロック、フレーム、表、およびその他のオブジェクトの階層として提示されます。これらは文書に論理的な構造を与え、その内容がどのように表示されるかを記述します。一般的に、フレームや表は他の構造をグループ化するために使用され、テキストブロックには実際のテキスト情報が含まれます。

新しい要素は、QTextCursor を使用してプログラムから、あるいはQTextEdit などのエディタウィジェットを使用して、ドキュメント内に作成・挿入されます。要素は作成時に特定の書式を指定することができます。指定がない場合は、その要素に対してカーソルの現在の書式が適用されます。

フレームとテキストブロックを用いたドキュメントの構成基本的な構造

ドキュメントの「最上位レベル」は、図に示すような方法で構成されることがあります。各ドキュメントには常にルートフレームが含まれており、このルートフレームには常に少なくとも1つのテキストブロックが含まれています。

テキストコンテンツを含むドキュメントの場合、ルートフレームには通常、一連のブロックやその他の要素が含まれます。

文書内では、フレームや表の連続は、たとえテキストブロックに情報が含まれていない場合でも、常にテキストブロックによって区切られています。これにより、既存の構造の間に新しい要素をいつでも挿入できるようになります。

この章では、リッチテキスト文書で使用される各構造要素について検討し、その特徴と用途を概説するとともに、その内容を調べる方法について説明します。文書の編集については、「QTextCursor インターフェース」で説明しています。

リッチテキスト文書

QTextDocument オブジェクトには、リッチテキスト文書を構築するために必要なすべての情報が含まれています。テキスト文書へのアクセスには、エディタが使用する線形バッファとしての方法と、レイアウトエンジンに有用なオブジェクト階層としての方法という、互いに補完し合う2つの方法があります。階層的な文書モデルにおいて、オブジェクトは一般的に、フレーム、表、リストなどの視覚的要素に対応しています。 より低レベルでは、これらの要素はテキストのスタイルや配置などのプロパティを記述しています。ドキュメントの線形表現は、ドキュメントの内容の編集や操作に使用されます。

QTextEdit を使用するとリッチテキストの表示や編集が容易になりますが、ドキュメントはエディタウィジェットとは独立して利用することも可能です。例えば:

QTextDocument *newDocument = new QTextDocument;

あるいは、既存のエディタからドキュメントを抽出することも可能です:

QTextEdit *editor = new QTextEdit;
QTextDocument *editorDocument = editor->document();

この柔軟性により、アプリケーションは、複数のエディタウィジェットによるオーバーヘッドや、文書を中間形式で保存する必要なしに、複数のリッチテキスト文書を扱うことができます。

空のドキュメントにはルートフレームが含まれており、そのフレーム自体には単一の空のテキストブロックが含まれています。フレームはドキュメントの各部分を論理的に分離するだけでなく、レンダリング時の表示方法を決定するプロパティも持っています。テーブルは、行と列に配置された多数のセルで構成される特殊なタイプのフレームであり、各セルにはさらに詳細な構造やテキストを含めることができます。 テーブルは、セルの柔軟な構成を可能にする管理およびレイアウト機能を提供します。

テキストブロックにはテキストフラグメントが含まれており、各フラグメントはテキストおよび文字の書式情報を指定します。 テキストのプロパティは、文字レベルとブロックレベルの両方で定義されます。文字レベルでは、フォントファミリー、テキストの色、フォントの太さなどのプロパティを指定できます。ブロックレベルのプロパティは、テキストの流れの方向、配置、背景色など、テキストのより高レベルの表示や挙動を制御します。

文書の構造は直接操作されません。編集はカーソルベースのインターフェースを通じて行われます。テキストカーソルインターフェースは、新しい文書要素をルートフレームに自動的に挿入し、必要に応じて空のブロックで埋め合わせを行います。

ルートフレームは、以下の方法で取得します。

    QTextDocument *editorDocument = editor->document();
    QTextFrame *root = editorDocument->rootFrame();

ドキュメント構造をナビゲートする際、ルートフレームから開始すると便利です。ルートフレームからはドキュメント構造全体にアクセスできるためです。

ドキュメント要素

リッチテキスト文書は通常、段落、フレーム、表、リストなどの一般的な要素で構成されます。これらはQTextDocument において、QTextBlock 、QTextFrame 、QTextTable 、およびQTextList クラスによって表されます。文書内の他の要素とは異なり、画像は特別にフォーマットされたテキストフラグメントによって表されます。これにより、画像を周囲のテキストとインラインでフォーマットされた状態で配置することが可能になります。

ドキュメントの基本的な構造構成要素は、QTextBlock およびQTextFrame です。ブロック自体はリッチテキストの断片(QTextFragment )を含んでいますが、これらはドキュメントの高レベル構造に直接影響を与えることはありません。

他の文書要素をグループ化できる要素は、通常、QTextObject のサブクラスであり、2つのカテゴリに分類されます。テキストブロックをグループ化する要素はQTextBlockGroup のサブクラスであり、フレームやその他の要素をグループ化する要素はQTextFrame のサブクラスです。

テキストブロック

テキストブロックは、QTextBlock クラスによって提供されます。

テキストブロックは、異なる文字形式を持つテキストの断片をまとめてグループ化し、ドキュメント内の段落を表すために使用されます。各ブロックには通常、異なるスタイルを持つ複数のテキスト断片が含まれます。断片は、テキストがドキュメントに挿入される際に作成され、ドキュメントが編集されるにつれてさらに追加されていきます。 ドキュメントは、ブロック内のさまざまなスタイルのテキストを効率的に表現するために、フラグメントの分割、結合、削除を行います。

特定のブロック内のフラグメントは、QTextBlock::iterator を使用してブロックの内部構造を走査することで確認できます:

    QTextBlock::iterator it;
    for (it = currentBlock.begin(); !(it.atEnd()); ++it) {
        QTextFragment currentFragment = it.fragment();
        if (currentFragment.isValid())
            processFragment(currentFragment);
    }

ブロックはリスト項目の表現にも使用されます。その結果、ブロックは、リスト項目に使用される箇条書き記号の種類など、ブロックレベルの装飾に関する情報を含む独自の文字書式を定義することができます。ブロック自体の書式設定は `QTextBlockFormat ` クラスによって記述され、テキストの配置、インデント、背景色などのプロパティを定義します。

特定のドキュメントには複雑な構造が含まれている場合もありますが、ドキュメント内の有効なブロックへの参照が得られれば、各テキストブロックを記述された順序で順次移動することができます:

    QTextBlock currentBlock = textDocument->begin();

    while (currentBlock.isValid()) {
        processBlock(currentBlock);
        currentBlock = currentBlock.next();
    }

このメソッドは、フレームや表、その他の構造を無視するため、ドキュメントからリッチテキストのみを抽出したい場合に便利です。

QTextBlock ブロックを操作しやすくするための比較演算子が用意されています。operator==() およびoperator!=() は、2 つのブロックが同一であるかどうかを判定するために使用され、operator<() は、ドキュメント内でどちらが先に現れるかを判定するために使用されます。

フレーム

フレームは、QTextFrame クラスによって提供されます。

テキストフレームは、テキストのブロックや子フレームをグループ化し、段落よりも大きなドキュメント構造を作成します。フレームのフォーマットは、ページ上でのレンダリング方法や配置方法を指定します。フレームは、テキストフロー内に挿入されるか、ページの左側または右側にフローティング表示されます。 各ドキュメントには、他のすべてのドキュメント要素を含むルートフレームが含まれています。その結果、ルートフレームを除くすべてのフレームには親フレームが存在します。

テキストブロックは他のドキュメント要素を区切るために使用されるため、各フレームには常に少なくとも1つのテキストブロックと、0個以上の子フレームが含まれます。QTextFrame::iterator を使用してフレームの子要素を順にたどることで、フレームの内容を確認できます:

    QTextFrame::iterator it;
    for (it = frame->begin(); !(it.atEnd()); ++it) {

        QTextFrame *childFrame = it.currentFrame();
        QTextBlock childBlock = it.currentBlock();

        if (childFrame)
            processFrame(childFrame);
        else if (childBlock.isValid())
            processBlock(childBlock);
    }

なお、このイテレータはフレームとブロックの両方を選択するため、どちらを指しているかを確認する必要があります。これにより、フレーム単位でドキュメント構造をナビゲートしつつ、必要に応じてテキストブロックにもアクセスすることが可能になります。QTextBlock::iterator クラスとQTextFrame::iterator クラスを相互に補完的に使用することで、ドキュメントから必要な構造を抽出することができます。

表

表は、QTextTable クラスによって提供されます。

表は、行と列に配置されたセルの集合です。各表セルは、独自の文字書式を持つドキュメント要素ですが、フレームやテキストブロックなどの他の要素を含むこともできます。表セルは、表が構築されたとき、または行や列が追加されたときに自動的に作成されます。また、表間で移動させることも可能です。

QTextTable はQTextFrame のサブクラスであるため、テーブルはドキュメント構造においてフレームと同様に扱われます。ドキュメント内で検出された各フレームについて、それがテーブルであるかどうかを判定し、それに応じて異なる処理を行うことができます:

    QTextFrame::iterator it;
    for (it = frame->begin(); !(it.atEnd()); ++it) {

        QTextFrame *childFrame = it.currentFrame();
        QTextBlock childBlock = it.currentBlock();

        if (childFrame) {
            QTextTable *childTable = qobject_cast<QTextTable*>(childFrame);

            if (childTable)
                processTable(childTable);
            else
                processFrame(childFrame);

        } else if (childBlock.isValid()) {
            processBlock(childBlock);
        }
    }

既存のテーブル内のセルは、行と列を順に処理することで調べることができます。

    for (int row = 0; row < table->rows(); ++row) {
        for (int column = 0; column < table->columns(); ++column) {
            QTextTableCell tableCell = table->cellAt(row, column);
            processTableCell(tableCell);
        }
    }

リスト

リストはQTextList クラスによって提供されます。

リストは、通常の方法で書式設定されたテキストブロックのシーケンスですが、箇条書きや番号付き項目といった標準的なリスト装飾も提供します。リストはネストすることができ、リストの書式でゼロ以外のインデントが指定されている場合は、インデントされます。

各リスト項目は、リスト内でのインデックスを指定することで参照できます:

    for (int index = 0; index < list->count(); ++index) {
        QTextBlock listItem = list->item(index);
        processListItem(listItem);
    }

QTextList はQTextBlockGroup のサブクラスであるため、リスト項目を子要素としてグループ化せず、代わりにそれらを管理するためのさまざまな関数を提供します。つまり、ドキュメントを走査する際に見つかるテキストブロックは、実際にはリスト項目である可能性があります。以下のコードを使用することで、リスト項目が正しく識別されるようにすることができます:

    QTextFrame::iterator it;
    for (it = frame->begin(); !(it.atEnd()); ++it) {

        QTextBlock block = it.currentBlock();

        if (block.isValid()) {

            QTextList *list = block.textList();

            if (list) {
                int index = list->itemNumber(block);
                processListItem(list, index);
            }
        }
    }

画像

QTextDocument における画像は、リソース機構を介して外部画像を参照するテキストフラグメントによって表現されます。画像はカーソルインターフェースを使用して作成され、後で画像のテキストフラグメントの文字形式を変更することで修正することができます:

    if (fragment.isValid()) {
        QTextImageFormat newImageFormat = fragment.charFormat().toImageFormat();

        if (newImageFormat.isValid()) {
            newImageFormat.setName(":/images/newimage.png");
            QTextCursor helper = cursor;

            helper.setPosition(fragment.position());
            helper.setPosition(fragment.position() + fragment.length(),
                                QTextCursor::KeepAnchor);
            helper.setCharFormat(newImageFormat);
        }
    }

画像を表すフラグメントは、その画像を含むテキストブロック内のフラグメントを反復処理することで見つけることができます。

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