Qt

【C++】QtのQTextEditで実装するリッチテキストエディタの基本とカスタム操作

QTのQTextEditは、リッチテキストを扱えるウィジェットで、シンプルにテキスト入力や編集が行えるのが魅力です。

HTMLタグを利用して書式設定が可能で、インタラクティブなエディタやビューを作る際に役立ちます。

必要に応じたカスタム操作も容易に実装でき、C++とQTを用いるプロジェクトに優れた柔軟性を提供します。

基本的な使い方

QTextEditのインスタンス生成

QtのQTextEditを使うためには、まずインスタンスを生成する必要があります。

新しいウィジェットを作る手続きはとてもシンプルで、new演算子を用いてインスタンスを作成し、適切な引数を渡すだけです。

以下のサンプルコードは、QTextEditウィジェットのインスタンス生成と基本的な設定を行った例です。

#include <QApplication>
#include <QTextEdit>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    // QTextEditのインスタンスを生成
    QTextEdit *textEdit = new QTextEdit;
    // 初期テキストを設定
    textEdit->setText("シンプルなテキストエディタのウィンドウです。");
    // ウィンドウを表示
    textEdit->show();
    return app.exec();
}
ウィンドウにテキストエディタが表示され、「シンプルなテキストエディタのウィンドウです。」という初期テキストが見えます。

テキストの設定と取得

QTextEditでは、プログラム中にテキストの設定と取得が容易に行える仕組みが用意されています。

ユーザーが入力したテキストを後から処理したり、プログラム側でフォーマットを変更する際に利用できます。

setTextとsetHtmlの使い分け

通常のプレーンなテキストはsetTextを使い、HTMLタグを含むリッチなテキストはsetHtmlを使うようにすると便利です。

例えば、以下のサンプルコードでは、それぞれの関数を用いたテキスト設定の例を示します。

#include <QApplication>
#include <QTextEdit>
#include <QTimer>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QTextEdit *textEdit = new QTextEdit;
    // プレーンテキストを設定する場合はsetTextを利用
    textEdit->setText("これはプレーンテキストです。");
    // 10秒後にリッチテキストを設定する例
    QTimer::singleShot(10000, [textEdit]() {
        // HTMLタグを含むリッチテキストをsetHtmlで設定
        textEdit->setHtml("<p style='color: green; font-size: 18px;'><b>リッチテキストのサンプル</b></p>");
    });
    textEdit->show();
    return app.exec();
}
ウィンドウに最初は「これはプレーンテキストです。」と表示され、10秒後に緑色でフォントサイズ18pxの太字リッチテキストに切り替わります。

toPlainTextとtoHtmlの活用

テキストを取得する際にも、内容の形式に合わせた関数を利用できます。

ユーザーが入力した内容を、プレーンテキストとして取得するにはtoPlainTextを利用し、装飾付きのHTML形式として取得したいときはtoHtmlを利用します。

この機能を利用すれば、編集後のテキストをファイルに保存したり、データベースに保存したりする際に柔軟な対応が可能です。

ウィジェットのレイアウトへの組み込み

QTextEditは単独で使用することもできますが、他のウィジェットと一緒に配置する場合はQtのレイアウトマネージャーと組み合わせることで、見た目の調整や自動配置が容易になります。

例えば、QVBoxLayoutQHBoxLayoutを使って、ウィンドウ内に複数のウィジェットを並べることができます。

以下は簡単な例です。

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QTextEdit>
#include <QPushButton>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout;
    // テキストエディタウィジェットの生成
    QTextEdit *textEdit = new QTextEdit;
    textEdit->setText("レイアウトに組み込まれたテキストエディタです。");
    // ボタンウィジェットの生成
    QPushButton *button = new QPushButton("ボタン");
    // レイアウトにウィジェットを追加
    layout->addWidget(textEdit);
    layout->addWidget(button);
    window.setLayout(layout);
    window.show();
    return app.exec();
}
ウィンドウに、上部にテキストエディタ、下部にボタンが縦に並んだ画面が表示されます。

リッチテキストの活用

HTML形式テキストの表示

QTextEditはHTML形式のリッチテキストを直接表示できるため、スタイル情報やレイアウトの指示をHTMLタグで記述することが可能です。

以下のコードは、HTMLのマークアップを利用して、テキストのフォントカラーやサイズの変更、太字の適用などを行った例です。

#include <QApplication>
#include <QTextEdit>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QTextEdit *textEdit = new QTextEdit;
    // HTML形式で書式設定を適用する
    textEdit->setHtml("<h2 style='color: purple;'>HTMLヘッダー</h2>"
                      "<p style='font-family: \"Arial\"; font-size: 14px;'>これはHTML形式で表示されたテキストです。</p>"
                      "<p style='color: red;'><i>斜体と赤色のテキストが含まれます。</i></p>");
    textEdit->show();
    return app.exec();
}
ウィンドウに、紫色の見出しとArialフォントで書かれた通常の文章、赤い斜体の文章が表示されます。

書式設定の適用

テキストの見た目を自在に変更するための設定が可能です。

ここでは、フォントスタイルやサイズ、カラー設定、背景色などについて触れます。

フォントスタイルとサイズの変更

フォントの種類やサイズ、スタイル(例えば太字や斜体など)は、QFontクラスを利用して設定することができます。

たとえば、以下のコードはテキストエディタ内でフォントの種類とサイズを変更する例になります。

#include <QApplication>
#include <QTextEdit>
#include <QFont>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QTextEdit *textEdit = new QTextEdit;
    textEdit->setText("フォントスタイルとサイズが変更されるサンプルテキスト。");
    // QFontを用いてフォントの設定
    QFont font("Times New Roman", 16);
    font.setBold(true);
    textEdit->setFont(font);
    textEdit->show();
    return app.exec();
}
ウィンドウ内に、Times New Romanの16ポイントで太字が適用されたテキストが表示されます。

カラー設定と背景色の調整

テキストや背景に色を付けるには、HTMLのスタイルシートやQTextCharFormatクラスを利用して設定が可能です。

HTMLを用いる場合は、setHtmlを使い、インラインスタイルで指定すれば反映されます。

また、動的な変更が必要な場合は、QTextCharFormatを用いてカーソル周辺のテキストの色を変更する方法があります。

以下は、カラーと背景色をHTMLを使って設定する例です。

#include <QApplication>
#include <QTextEdit>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QTextEdit *textEdit = new QTextEdit;
    // HTMLのスタイル指定でテキストカラーおよび背景色を設定
    textEdit->setHtml("<p style='color: #ff5733; background-color: #f0f0f0; font-size: 15px;'>カラーと背景色が設定されたテキスト</p>");
    textEdit->show();
    return app.exec();
}
ウィンドウに、オレンジがかったテキストと薄いグレーの背景を持つテキストが表示されます。

テキストフォーマットのカスタマイズ

QTextEditでは、QTextCharFormatQTextBlockFormatなどのクラスを利用して、細かいフォーマットの調整ができます。

これにより、特定の文字列に対して太字や斜体、下線などの装飾をプログラムから簡単に適用することが可能です。

また、エディタ内の指示に応じたフォーマット変更も柔軟に実現できるため、ユーザーにとって使いやすいエディタが実装できます。

テキストの読み書き機能

ファイルからのテキスト読み込み

ファイルに保存されているテキストを読み込み、QTextEditに表示する機能は、アプリケーションの実用性を向上させます。

QFileQTextStreamを用いて、以下のようなシンプルな実装が可能です。

#include <QApplication>
#include <QTextEdit>
#include <QFile>
#include <QTextStream>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QTextEdit *textEdit = new QTextEdit;
    // sample.txtからテキストを読み込む
    QFile file("sample.txt");
    if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QTextStream in(&file);
        // 読み込んだテキストをエディタに反映
        textEdit->setText(in.readAll());
        file.close();
    }
    textEdit->show();
    return app.exec();
}
sample.txtに存在するテキスト内容が、ウィンドウ内のテキストエディタに表示されます。

編集内容の保存

ユーザーがエディットした内容を保存する機能は、とても重要なポイントです。

以下に、編集内容の保存に関する2つの側面を紹介します。

自動保存機能の実装

テキストの変更があった際に、自動でファイルに保存する仕組みを利用すれば、ユーザーが意図せず編集内容を失わないようにできる場合があります。

QObject::connectを利用して、textChangedシグナルと保存処理を連携させる実装例を紹介します。

#include <QApplication>
#include <QTextEdit>
#include <QFile>
#include <QTextStream>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QTextEdit *textEdit = new QTextEdit;
    textEdit->setText("ここにテキストを入力してください。");
    // テキストが変更されるたびに保存処理を行う
    QObject::connect(textEdit, &QTextEdit::textChanged, [textEdit]() {
        QFile file("autosave.txt");
        if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream out(&file);
            // 現在のテキスト内容を保存
            out << textEdit->toPlainText();
            file.close();
        }
    });
    textEdit->show();
    return app.exec();
}
エディタ内でテキストを変更するたびに、「autosave.txt」に最新の内容が書き込まれます。
※autosave.txtはカレントディレクトリに作成されます

保存形式の選択

テキストの保存時には、純粋なプレーンテキストとして保存するか、またはHTMLなどのリッチテキスト形式として保存するか、選べるようにしておくと利用シーンに応じた柔軟な対応が可能になります。

例えば、プレーンテキストとして保存する場合はtoPlainTextを利用し、HTML形式で保存する場合にはtoHtmlを利用します。

以下は、簡単な保存形式選択の例です。

#include <QApplication>
#include <QTextEdit>
#include <QFile>
#include <QTextStream>
#include <QPushButton>
#include <QVBoxLayout>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QTextEdit *textEdit = new QTextEdit;
    textEdit->setText("保存形式を選んでテキストを保存する例。");
    // ボタンでプレーンテキストとして保存する例
    QPushButton *saveButton = new QPushButton("プレーンテキスト保存");
    QObject::connect(saveButton, &QPushButton::clicked, [textEdit]() {
        QFile file("plain.txt");
        if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream out(&file);
            out << textEdit->toPlainText();
            file.close();
        }
    });
    // ボタンでHTML形式として保存する例
    QPushButton *htmlSaveButton = new QPushButton("HTML形式保存");
    QObject::connect(htmlSaveButton, &QPushButton::clicked, [textEdit]() {
        QFile file("richtext.html");
        if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream out(&file);
            out << textEdit->toHtml();
            file.close();
        }
    });
    // 簡易ウィンドウレイアウトに配置する
    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(textEdit);
    layout->addWidget(saveButton);
    layout->addWidget(htmlSaveButton);
    window.setLayout(layout);
    window.show();
    return app.exec();
}
ウィンドウにテキストエディタと2つのボタンが表示され、各ボタンを押すとそれぞれプレーンテキストまたはHTML形式でファイルが保存されます。

カスタム操作の実装

カスタムコンテキストメニューの作成

QTextEditでは、右クリック時に表示されるコンテキストメニューをカスタマイズすることができます。

ユーザーの操作に応じた便利なアクションを追加することで、エディタの使いやすさが向上します。

メニュー項目の追加方法

以下の例は、QTextEditを継承して独自のコンテキストメニューを実装する方法です。

標準メニューに加えて、新たに「太字」のメニュー項目を追加し、選択されたテキストの装飾を変更する動作を実現します。

#include <QApplication>
#include <QTextEdit>
#include <QMenu>
#include <QAction>
#include <QContextMenuEvent>
#include <QTextCursor>
#include <QTextCharFormat>
#include <QFont>
class CustomTextEdit : public QTextEdit {
public:
    CustomTextEdit(QWidget *parent = nullptr) : QTextEdit(parent) {}
protected:
    // コンテキストメニューイベントのオーバーライド
    void contextMenuEvent(QContextMenuEvent *event) override {
        QMenu *menu = createStandardContextMenu(event->pos());
        // 新しいアクション「太字」をメニューに追加
        QAction *boldAction = new QAction("太字", this);
        connect(boldAction, &QAction::triggered, this, &CustomTextEdit::applyBold);
        menu->addAction(boldAction);
        menu->exec(event->globalPos());
    }
private:
    // 太字の書式を適用するメソッド
    void applyBold() {
        QTextCursor cursor = textCursor();
        QTextCharFormat format;
        format.setFontWeight(QFont::Bold);
        // 現在のカーソル位置に書式を適用
        cursor.mergeCharFormat(format);
        setTextCursor(cursor);
    }
};
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    CustomTextEdit editor;
    editor.setWindowTitle("カスタムコンテキストメニュー付きエディタ");
    editor.setText("右クリックでカスタムメニューを表示できます。");
    editor.resize(400, 300);
    editor.show();
    return app.exec();
}
ウィンドウにエディタが表示され、右クリックすると標準メニューに加え「太字」アクションが表示されます。選択したテキストに「太字」の効果が反映されます。

独自アクションとの連携

他にもユーザーの操作やアプリケーションの文脈に応じた独自アクションを実装することが可能です。

例えば、テキストの色変更やフォントサイズの調整アクションを追加すれば、エディタのカスタマイズ性が向上し、使い勝手の良いインターフェースを提供できるようになります。

これらは先述のapplyBoldメソッドと同様の手法で実装可能です。

キーボードショートカットの設定

テキスト編集中に頻繁に使われる操作は、キーボードショートカットを設定することで効率よく実行できます。

Qtでは、QShortcutクラスを利用して特定のキー入力に応じたスロットを呼び出す仕組みが提供され、エディタ全体の操作性を豊かにすることが可能です。

例えば、Ctrl+Bを押すと選択範囲が太字になるといった機能を実装することができるため、操作のスピードが向上します。

イベントのオーバーライド

QTextEditに対して様々なイベントをオーバーライドすることで、より細かいユーザーインターフェースのカスタマイズが可能になります。

contextMenuEventの活用

先述のカスタムコンテキストメニューの例のように、contextMenuEventをオーバーライドすることで、右クリックメニューに独自のアクションを追加することができます。

この技法は、ユーザーの直感的な操作に沿った機能を実現する上で非常に便利な手法といえます。

keyPressEventの拡張

キーボード入力に対しても、keyPressEventをオーバーライドすることで、例えば特定のキー組み合わせが入力された場合にカスタム動作を実行することが可能です。

以下は、Enterキーが押された際に特定の処理を追加する例です。

#include <QApplication>
#include <QTextEdit>
#include <QKeyEvent>
#include <QDebug>
class CustomKeyTextEdit : public QTextEdit {
public:
    CustomKeyTextEdit(QWidget *parent = nullptr) : QTextEdit(parent) {}
protected:
    void keyPressEvent(QKeyEvent *event) override {
        if (event->key() == Qt::Key_Return) {
            // Enterキーが押された時のカスタム処理
            qDebug() << "Enterキーが押されました。";
        }
        // デフォルトの挙動も維持
        QTextEdit::keyPressEvent(event);
    }
};
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    CustomKeyTextEdit editor;
    editor.setText("Enterキーを押すとコンソールにメッセージが表示されます。");
    editor.resize(400, 300);
    editor.show();
    return app.exec();
}
ウィンドウにエディタが表示され、Enterキーを押すとコンソールに「Enterキーが押されました。」と出力されます。

シグナルとスロットの連携

Qtフレームワークの大きな魅力のひとつは、シグナルとスロットを連携させたイベント駆動型のプログラミング手法です。

QTextEditでもこの仕組みを利用して、編集内容の変化やユーザーの操作に対して即座に反応することが可能となります。

textChangedシグナルの利用

QTextEditはテキストが変更された際にtextChangedシグナルを発行します。

このシグナルと任意のスロットを接続することで、ユーザーの入力に応じた動作(例えば、状態の更新や自動保存)が実現できます。

#include <QApplication>
#include <QTextEdit>
#include <QDebug>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QTextEdit *textEdit = new QTextEdit;
    textEdit->setText("テキストが変更された時にシグナルが発生します。");
    QObject::connect(textEdit, &QTextEdit::textChanged, [textEdit]() {
        qDebug() << "テキストが変更されました:" << textEdit->toPlainText();
    });
    textEdit->show();
    return app.exec();
}
ウィンドウでテキストを編集すると、コンソールに最新のテキスト内容が出力されます。

編集完了時の反応処理

ユーザーがテキストの編集を終了したタイミングで反応する仕組みも、シグナルとスロットで実装できます。

例えば、フォーカスが外れた際に内容を確認するなどの操作を行うと、エディタの操作性が向上します。

この場合、focusOutEventや別途定義したシグナルを利用する工夫が考えられます。

テキスト選択変更の検出

テキストの選択範囲が変わったタイミングでも、適切なシグナルを発行して処理を連携することができます。

これにより、選択されたテキストに対するカスタム操作(色の変更や書式調整など)を即座に行えるようになります。

この種の連携はインタラクティブなエディタで特に役立つ機能と言えるでしょう。

フォントと文字フォーマット操作

QTextEditでは、QTextCharFormatを利用することで、テキストの細かい書式設定を行うことが可能です。

カーソルの操作と組み合わせると、ユーザーが選択した部分に対して即座に書式変更を適用したり、保存したりできるので、とても使いやすい機能が揃っています。

QTextCharFormatの基本操作

QTextCharFormatは文字のフォーマットに関する情報を保持するクラスです。

新たなフォーマットを設定する場合や、現在のカーソル位置のフォーマットを調べる場合に活用できます。

例えば、以下のコードはカーソル位置のテキストを太字に変更する例です。

#include <QApplication>
#include <QTextEdit>
#include <QTextCharFormat>
#include <QFont>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QTextEdit *textEdit = new QTextEdit;
    textEdit->setText("カーソル位置のテキストに書式を適用する例です。");
    // 太字に変更するためのフォーマット設定
    QTextCharFormat format;
    format.setFontWeight(QFont::Bold);
    // カーソル操作で適用する処理(ここではサンプルとして自動的に全体に適用)
    QTextCursor cursor = textEdit->textCursor();
    cursor.select(QTextCursor::Document);
    cursor.mergeCharFormat(format);
    textEdit->setTextCursor(cursor);
    textEdit->show();
    return app.exec();
}
ウィンドウに表示されるテキスト全体が太字で描かれた状態になります。

フォントプロパティの設定

書式設定におけるフォントのプロパティ設定は、テキストの見た目を決定づける重要な要素です。

QTextCharFormatのメソッドを利用して、太字、斜体、アンダーライン、カラーの調整などを行うことができます。

太字・斜体の適用

setFontWeightsetFontItalicなどの関数を利用すれば、選択されたテキストに対して太字や斜体の書式を簡単に適用できます。

この機能はユーザーが入力中にリアルタイムでフォーマットを変更する際に、大変役立ちます。

アンダーラインとカラーの調整

さらに、アンダーラインの追加や、文字色の変更は、setFontUnderlinesetForegroundで実現できます。

これらを組み合わせることで、個々のテキストに多彩な装飾を与えることが可能です。

カーソル操作による書式適用

カーソルの位置を取得して、その部分に対して書式を変更する操作は、とても直感的に実装できます。

ユーザーがテキストを選択した際に、あるいは入力中にキー操作で書式を変更するイベントをトリガーに、カーソル位置に対して適用する書式を変更する方法が採用されることが多いです。

これにより、編集内容の修正が迅速に反映され、ユーザーにとって使いやすいインターフェースを提供できるようになります。

カスタムスタイルの導入

スタイルシートの利用

Qtでは、ウィジェットに対してスタイルシート(CSS記法に近い形式)を適用することが可能です。

QTextEditも例外ではなく、背景色、文字色、枠線など多くのプロパティをスタイルシートで設定できます。

これにより、アプリケーション全体で統一感のあるデザインを実現しやすくなります。

CSS記法の基本

簡単な例として、以下のコードはQTextEditに対して背景色や文字色を設定する方法を示します。

#include <QApplication>
#include <QTextEdit>
int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    QTextEdit *textEdit = new QTextEdit;
    textEdit->setText("スタイルシートで装飾されたテキストエディタです。");
    // CSS記法を用いて背景色と文字色を設定
    textEdit->setStyleSheet("QTextEdit { background-color: #eaffea; color: #003300; font-size: 14px; }");
    textEdit->show();
    return app.exec();
}
ウィンドウに、淡い緑の背景と濃い緑の文字色が適用されたテキストエディタが表示されます。

カラースキームの設定

スタイルシートを活用すれば、全体のカラースキームを柔軟に調整できます。

特に、ダークモードやライトモードなどのテーマ機能を実現する際に、動的にスタイルシート内容を変更することで、ユーザーにとって見やすいインターフェースが提供できるようになります。

ユーザーインターフェースの統一感向上

スタイルシートやフォント、カラー設定を上手に組み合わせることで、アプリケーション全体に統一感のあるUIを提供できます。

ウィンドウ内のテキストエディタ、ボタン、ラベルなどのウィジェットに一貫したデザイン方針を適用することで、ユーザーは自然と使いやすいと感じるようになります。

この点は、エディタ単体でなくアプリケーション全体でデザインを揃えるときに大切なポイントです。

拡張可能なカスタマイズ例

複数エディタ間の連携

複数のQTextEditウィジェットを用いて、異なるファイルや文書間で連携した操作を実装することも可能です。

例えば、サイドバーでファイル一覧を表示し、選択したファイルの内容が中央のエディタに読み込まれるといった連携は、ユーザーの操作性を大きく向上させます。

各エディタの内容を同期的に更新することで、編集作業がスムーズになります。

プラグイン形式による機能拡張

ユーザーのニーズやシステム拡張に合わせて、プラグイン形式で機能拡張を行う設計も魅力です。

プラグインを利用すれば、基本的なリッチテキストエディタに対して、コードの補完、シンタックスハイライトや、外部ツールとの連携などの追加機能を柔軟に実装できます。

モジュール化の設計方針

プラグイン形式の拡張を行う際には、各機能が独立して動作し、必要に応じて読み込み・アンロードができるようにモジュール化する設計が望ましいです。

この方法を採用すれば、メンテナンスも楽になり、ユーザーからのフィードバックに応じた素早い機能追加が実現できます。

機能追加のポイント

機能拡張を行う際のポイントとしては、簡単なユーザー操作で有用な機能が呼び出せること、そして既存機能との整合性が保たれるような設計を心がけることが挙げられます。

実際のシステム設計の際には、各プラグインがどのシグナルと連携するのか、どのウィジェットに対して影響を及ぼすのか、十分に検討する必要があります。

まとめ

今回の記事では、QtのQTextEditを用いたリッチテキストエディタの基本的な使い方から、リッチテキストの活用法、テキストの読み書き、カスタム操作、シグナルとスロットの連携、フォントや文字フォーマットの操作、さらにはカスタムスタイルの導入と拡張例に至るまで、幅広い内容を取り上げました。

各項目ごとにサンプルコードを交えながら説明してきたので、実際のプロジェクトに合わせた改変や拡張も十分に試すことができると感じられると思います。

ぜひ柔軟に試してみて、使いやすいエディタ作成の一助として役立ててもらえれば嬉しいです。

関連記事

Back to top button
目次へ