Qt

【C++】Qt QPlainTextEditの使い方:シンプルなテキスト編集機能の実装方法

QPlainTextEdit は、Qt の C++ アプリでシンプルなテキスト編集を行うためのウィジェットです。

コードエディタやログ表示などに適しており、setPlainTextappendPlainTextなどの関数でテキスト操作が簡単に実現できます。

シグナルとスロットを使い、ユーザー操作に柔軟に反応できる仕組みが特徴です。

QPlainTextEdit の基本

役割と特徴

QPlainTextEditは、シンプルなプレーンテキストの編集を行うウィジェットです。

大容量のテキストも高速に処理でき、ソースコードやログの表示、編集に適しています。

読み込みや書き込みなどの基本機能に加え、フォントや文字色の設定、タブ幅の調整なども柔軟に変更できる点が魅力です。

他のテキストウィジェットとの比較

QPlainTextEditは、リッチテキストに対応したQTextEditと比較すると、シンプルな構造になっています。

  • 余分な装飾処理が無いため、パフォーマンスが優れている
  • プレーンテキストに特化しているため、複雑なレイアウトや書式設定が不要な場面に最適な選択となる

そのため、ソースコードエディタや大容量のログ表示など、動作速度が求められる用途に向いています。

オブジェクトの生成と基本設定

インスタンス生成の基本

QPlainTextEditのインスタンス生成は、通常のQtウィジェットと同様に行います。

ウィジェットとしてスタックに追加するか、レイアウトに組み込むことで、簡単に利用することが可能です。

例えば、以下のコードはQPlainTextEditの基本的な生成方法の例です。

#include <QApplication>
#include <QPlainTextEdit>
#include <QWidget>
#include <QVBoxLayout>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    // QPlainTextEditのインスタンス生成
    QPlainTextEdit *plainTextEdit = new QPlainTextEdit;
    layout->addWidget(plainTextEdit);
    window.show();
    return a.exec();
}
(ウィンドウにシンプルなQPlainTextEditのエディタが表示されます)

初期設定と主要メソッド

QPlainTextEditの初期設定では、テキストの初期値設定、フォント、文字色、タブ幅などを設定することができます。

編集可能とするかどうかや、リードオンリーの設定もここで調整可能です。

初期状態の設定を適切に行うことで、ユーザーの操作性を向上させる工夫がなされます。

setPlainText と toPlainText の利用

setPlainTextはエディタの内容を一括して設定するためのメソッドです。

対してtoPlainTextは現在のテキスト内容を取得するために用います。

下記のコードサンプルはその利用方法を示しています。

#include <QApplication>
#include <QPlainTextEdit>
#include <QWidget>
#include <QVBoxLayout>
#include <QDebug>
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    // QPlainTextEditの作成
    QPlainTextEdit *plainTextEdit = new QPlainTextEdit;
    layout->addWidget(plainTextEdit);
    // テキストを設定
    plainTextEdit->setPlainText("こんにちは、Qtの世界!\n新しい行を追加します。");
    // テキストを取得してデバッグ出力
    QString text = plainTextEdit->toPlainText();
    qDebug() << text;
    window.show();
    return app.exec();
}

コード内のコメントが示す通り、setPlainTextで設定した内容をそのままtoPlainTextで取得して出力しています。

簡単なテキスト操作を行う場合に非常に便利です。

appendPlainText と insertPlainText の挙動の違い

appendPlainTextは、既存のテキスト内容の末尾に新しいテキストを追加します。

一方、insertPlainTextはカーソル位置に新しいテキストを挿入します。

以下のコードサンプルでその違いが確認できます。

#include <QApplication>
#include <QPlainTextEdit>
#include <QWidget>
#include <QVBoxLayout>
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QPlainTextEdit *plainTextEdit = new QPlainTextEdit;
    layout->addWidget(plainTextEdit);
    // 初期テキストを設定
    plainTextEdit->setPlainText("初期テキスト\n");
    // appendPlainTextで末尾にテキストを追加
    plainTextEdit->appendPlainText("末尾に追加されたテキスト");
    // カーソルを先頭に移動してからinsertPlainTextで挿入
    plainTextEdit->moveCursor(QTextCursor::Start);
    plainTextEdit->insertPlainText("先頭に挿入されたテキスト\n");
    window.show();
    return app.exec();
}

上記のサンプルでは、カーソル位置の操作に基づいて印象的な挿入位置の違いを確認できるようになっています。

レイアウトへの組み込みと配置

レイアウトコンテナとの統合

QPlainTextEditは、Qtのレイアウトシステムとスムーズに連携します。

ウィジェットの自動リサイズや配置を調整するために、QVBoxLayoutやQHBoxLayoutなどのコンテナと組み合わせるのが一般的です。

レイアウトに追加する際は、レイアウトの基本方針(マージン・スペーシング)も考慮して配置設定するのが望ましいです。

サイズ調整の基本方針

ウィジェットのサイズは、レイアウトやウィンドウ全体でのスペース分配に依存します。

  • 最小サイズや最大サイズを設定することで、レイアウト中での柔軟なサイズ調整を実現
  • サイズ方針プロパティを用いると、特定のサイズに合わせた表示が可能

自動サイズと固定サイズの設定

自動サイズ設定では、ウィジェットが親ウィジェット全体のレイアウトに合わせてサイズ調整することが可能です。

固定サイズ設定では、ウィジェットのサイズを固定し、それに伴いテキスト領域が制限されるため、デザイン上の意図を反映することができます。

例えば、以下のように固定サイズを設定するケースがあります。

#include <QApplication>
#include <QPlainTextEdit>
#include <QWidget>
#include <QVBoxLayout>
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QPlainTextEdit *plainTextEdit = new QPlainTextEdit;
    // 固定サイズ設定
    plainTextEdit->setFixedSize(400, 300);
    layout->addWidget(plainTextEdit);
    window.show();
    return app.exec();
}
(サイズが400×300ピクセルに固定されたQPlainTextEditが表示されます)

シグナルとスロットによるイベント処理

テキスト変更イベントの連携

QPlainTextEditは、textChangedシグナルを提供しており、テキストの更新時に自動的に通知が行われる仕組みがあります。

シグナルとスロットを活用することで、テキスト変更に応じたリアルタイムな処理やログの記録が可能となります。

接続例として以下のコードがあります。

#include <QApplication>
#include <QPlainTextEdit>
#include <QWidget>
#include <QVBoxLayout>
#include <QDebug>
class TextEditor : public QPlainTextEdit
{
    Q_OBJECT
public:
    TextEditor(QWidget *parent = nullptr) : QPlainTextEdit(parent)
    {
        connect(this, &QPlainTextEdit::textChanged, this, &TextEditor::onTextChanged);
    }
public slots:
    void onTextChanged()
    {
        qDebug() << "テキスト内容が変更されました。";
    }
};
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    TextEditor *editor = new TextEditor;
    layout->addWidget(editor);
    window.show();
    return app.exec();
}
#include "main.moc"
(テキスト変更時に、デバッグ出力ウィンドウに「テキスト内容が変更されました。」と表示されます)

カーソル操作と連動機能

カーソル位置の管理

カーソル位置の管理により、ユーザーの入力位置に合わせた処理が可能です。

QTextCursorクラスを利用すると、カーソルの移動、選択範囲の取得、テキストの挿入位置の調整が行えるため、より直感的なテキスト編集体験が実現されます。

例えば、特定位置にカーソルを移動するサンプルコードは以下の通りです。

#include <QApplication>
#include <QPlainTextEdit>
#include <QWidget>
#include <QVBoxLayout>
#include <QTextCursor>
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget window;
    QVBoxLayout layout(&window);
    QPlainTextEdit plainTextEdit;
    plainTextEdit.setPlainText("行1\n行2\n行3");
    layout.addWidget(&plainTextEdit);
    // カーソルを2行目の先頭に移動する
    QTextCursor cursor = plainTextEdit.textCursor();
    cursor.movePosition(QTextCursor::Start);
    cursor.movePosition(QTextCursor::Down);
    plainTextEdit.setTextCursor(cursor);
    window.show();
    return app.exec();
}
(表示されたエディタ内で、カーソルが2行目の先頭に配置されます)

カスタムカーソル処理の実装

独自のテキスト編集動作を実装するために、カーソルの動作を細かく制御することも可能です。

例えば、特定のキー入力に対してカーソル移動以外の処理を追加する場合、keyPressEventをオーバーライドして実装します。

#include <QApplication>
#include <QPlainTextEdit>
#include <QKeyEvent>
#include <QDebug>
// CustomTextEditはQPlainTextEditを継承して、キー入力処理をカスタマイズする例
class CustomTextEdit : public QPlainTextEdit
{
public:
    CustomTextEdit(QWidget *parent = nullptr) : QPlainTextEdit(parent) {}
protected:
    void keyPressEvent(QKeyEvent *event) override
    {
        // Ctrl+Lキーが押された場合、カーソルをウィジェットの中央に移動する処理を追加
        if (event->modifiers() & Qt::ControlModifier && event->key() == Qt::Key_L) {
            QTextCursor cursor = textCursor();
            int moveSteps = document()->blockCount() / 2;
            for (int i = 0; i < moveSteps; ++i) {
                cursor.movePosition(QTextCursor::Down);
            }
            setTextCursor(cursor);
            qDebug() << "Ctrl+Lキーが押されたため、カーソル位置を中央に移動しました。";
        } else {
            // それ以外のキー入力は基本の処理を実行
            QPlainTextEdit::keyPressEvent(event);
        }
    }
};
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    CustomTextEdit editor;
    editor.setPlainText("行1\n行2\n行3\n行4\n行5\n行6");
    editor.resize(400, 300);
    editor.show();
    return app.exec();
}
(Ctrl+Lキーを押すと、エディタ内でカーソルが中央付近へ移動し、デバッグ出力に移動メッセージが表示されます)

テキスト編集操作の詳細

テキストの挿入・削除操作

QPlainTextEditでは、テキスト操作のための多様なメソッドが用意されています。

  • insertPlainTextを用いれば、カーソル位置に新しいテキストを挿入できる
  • clearメソッドで全テキストを削除できる

これらのメソッドを組み合わせることで、動的なテキスト編集に対応可能です。

テキスト選択とクリア機能

ユーザーが指定した文字列を選択する場合、QTextCursorselectメソッドなどを活用できます。

また、clearメソッドを利用すれば、エディタ内のテキストを一括でリセットできるため、操作の単純化につながります。

Undo / Redo 対応の検討

QPlainTextEditは、内部でUndo / Redoのスタックを保持しています。

ユーザーによる入力ミスの補正や、セルフチェック機能との連動が可能となるため、編集操作の取り消しと再実行を容易に実装できます。

必要に応じて、undo()redo()メソッドを呼び出すことで対応できます。

UIカスタマイズとスタイル調整

フォントとテキストカラーの設定

フォントや文字色のカスタマイズは、ユーザーインターフェースの調和を図るために有用です。

  • setFontメソッドを利用して、好みのフォントやサイズを設定できる
  • setTextColor(またはQPaletteを利用)により、テキストカラーが変更可能

コードサンプルの例を参考に、実際の動作を確認するとよいです。

タブ幅・インデントの調整

テキストエディタにおいては、タブ幅やインデントの設定が読みやすさ向上に寄与します。

QPlainTextEditでは、setTabStopDistanceメソッドを使用してタブ幅を指定できます。

Qt 5.10以前ではsetTabStopDistanceではなくsetTabStopDWidthを使用します。古いバージョンを使う場合は注意してください。

カスタムインデントの実装も、テキスト操作の際に柔軟に対応することが可能です。

タブ幅設定の方法

タブ幅設定は、エディタ全体の整列を整える重要なポイントです。

下記のサンプルはタブ幅を設定する例となっています。

#include <QApplication>
#include <QPlainTextEdit>
#include <QWidget>
#include <QVBoxLayout>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QWidget window;
    QVBoxLayout layout(&window);
    QPlainTextEdit plainTextEdit;

    // タブ幅を40ピクセルに設定(setTabStopWidth の代わりに setTabStopDistance を使用)
    plainTextEdit.setTabStopDistance(40);

    plainTextEdit.setPlainText("タブ\t幅の例\n次の行も\tタブ処理されています。");
    layout.addWidget(&plainTextEdit);
    window.show();
    return app.exec();
}

インデント調整のポイント

プログラムソースコードなどを扱う場合、均等なインデントが読みやすさに直結します。

  • インデント用のスペースやタブ文字の扱いに注意
  • QPlainTextEdit内で自動補完機能を実装することで、一貫性のあるインデントが可能になる

パフォーマンスとトラブルシューティング

大量テキスト処理時の注意点

大量のテキストを扱うとき、エディタの反応速度やメモリ使用量が懸念されます。

  • レンダリング処理が遅くならないよう、テキストの更新回数やサイズを注意深く制御する
  • 更新が必要なタイミングでのみ表示を更新する工夫が求められます

パフォーマンス向上のポイント

エディタのパフォーマンスを維持するために、以下の点に気を付けるとよいです。

  • 表示不具合への対処
    • ウィジェットの再描画を最小限に抑える
    • バックグラウンドでの処理を活用する
  • テキスト操作のレスポンス改善
    • 大量データの処理を分割して実行する
    • 不要な更新を避けるロジックを実装する

表示不具合への対処

ウィジェットのサイズやフォントの設定ミスが原因で表示がおかしくなる場合、以下のチェックが有効です。

  • 適切なフォントが設定されているか
  • ウィジェットサイズが十分に確保されているか
  • ウィジェットの再描画を強制するメソッド(update()など)の利用

テキスト操作のレスポンス改善

操作が重い場合、以下の対策が考えられます。

  • 更新の頻度を調整する
  • QPlainTextEdit固有の最適化オプションを検討する
  • QTimerを利用して更新をまとめると、レスポンスが向上する場合があります

他のQtウィジェットとの連携

QSyntaxHighlighterとの組み合わせ

QPlainTextEditは、QSyntaxHighlighterと組み合わせることで、ソースコードの構文ハイライトが実現しやすくなります。

  • highlightBlock関数をオーバーライドして、特定パターンに対する色付けが可能
  • シンプルなエディタから高機能なエディタへと発展させる際に役立ちます

独自ウィジェットとの統合方針

既存のQtウィジェットや、独自に作成したウィジェットとの連携もスムーズに行えます。

ウィジェット間でシグナルやスロットを利用し、動的なデータ交換が容易となる点が大きな魅力です。

ウィジェット間の通信方法

ウィジェット間の通信は、以下のポイントを活用することで実現できます。

  • カスタムシグナルを定義し、必要なデータを送信する
  • 複数のウィジェット間で共通のデータソースを参照する
  • イベントフィルタを利用して、グローバルなキー入力などを共有する

例えば、エディタでテキスト内容が変更された際に、別のウィジェットへ変更通知を送るといった実装が可能です。

まとめ

今回紹介した内容は、QPlainTextEditを利用したシンプルなテキスト編集機能の各要素について説明しています。

各設定や動作の違い、さらにレイアウトやシグナルとの連携方法など、実際のコードで確認できる例を交えながら詳しく解説しました。

柔軟なカスタマイズが可能なQPlainTextEditを活用することで、さまざまなアプリケーションで快適なテキスト編集環境を構築する助けとなるでしょう。

今後の開発の参考になれば幸いです。

関連記事

Back to top button
目次へ