Qt アプリ開発:テキストエディタの下線機能を実装する(setFontUnderline, QTextCharFormat)

2025-05-27

void QTextEdit::setFontUnderline()」は、QtフレームワークにおけるQTextEditクラスのメンバ関数の一つです。この関数は、現在テキストエディタ内で選択されているテキスト、またはカーソル位置にあるテキストのフォントに下線を設定するために使用されます。

より具体的に説明すると、以下のようになります。

  • setFontUnderline(): これが関数の名前であり、その機能を示唆しています。「font」(フォント)に対して「Underline」(下線)を「set」(設定する)という意味になります。
  • QTextEdit
    : これは、setFontUnderline()関数がQTextEditというクラスに属していることを示しています。QTextEditは、リッチテキストを表示および編集するためのウィジェット(GUI部品)です。
  • void: これは関数の戻り値の型を示しており、この関数は何も値を返さない(void)という意味です。

この関数がどのように動作するか:

  1. テキストが選択されている場合
    ユーザーがQTextEdit内で特定のテキスト範囲を選択している状態でこの関数を呼び出すと、選択されたテキスト全体に下線が適用されます。
  2. テキストが選択されていない場合(カーソルが位置している場合)
    テキストが選択されていない状態でこの関数を呼び出すと、そのカーソル位置に新しく入力されるテキストから下線が適用されるようになります。もしカーソル位置に既にテキストが存在する場合、そのテキストには影響を与えません。

使用例(C++のコード):

```cpp #include <QApplication> #include <QTextEdit> #include <QPushButton> #include <QVBoxLayout> #include <QWidget>

int main(int argc, char *argv[]) { QApplication app(argc, argv);

QWidget window;
QVBoxLayout *layout = new QVBoxLayout(&window);
QTextEdit *textEdit = new QTextEdit();
QPushButton *underlineButton = new QPushButton("下線を引く");

layout->addWidget(textEdit);
layout->addWidget(underlineButton);

QObject::connect(underlineButton, &QPushButton::clicked, [=]() {
    textEdit->setFontUnderline(true); // 下線を設定
});

window.setLayout(layout);
window.show();

return app.exec();

}



  1. 期待通りに下線が表示されない

    • 原因
      • フォントが下線をサポートしていない
        使用しているフォントによっては、下線が表示されないことがあります。
      • 他のフォント設定が優先されている
        例えば、スタイルシートやリッチテキスト形式(HTMLなど)で明示的に下線がオフになっている可能性があります。
      • ペイントの問題
        ごく稀に、グラフィックドライバやQtのレンダリングの問題で正しく描画されないことがあります。
    • トラブルシューティング
      • 別のフォントを試す
        異なるフォントを設定してみて、下線が表示されるか確認してください。QFont クラスを使ってフォントを設定できます。
      • スタイルシートの確認
        setStyleSheet()text-decoration: underlinenone になっていないか確認してください。また、親ウィジェットやアプリケーション全体に適用されているスタイルシートも影響を与える可能性があります。
      • リッチテキストの確認
        setHtml()setMarkdown() でテキストを設定している場合、それらのフォーマット内で下線が意図せず上書きされていないか確認してください。例えば、<u> タグが適切に使用されているか、<span style="text-decoration: none;"> のようなスタイルが適用されていないかなどを確認します。
      • 強制的な再描画
        viewport()->update() を呼び出して、ウィジェットの再描画を強制してみるのも有効かもしれません(ただし、根本的な解決にはならないことが多いです)。
      • Qtのバージョンやプラットフォームの確認
        特定のQtのバージョンやプラットフォームでのみ発生する問題かもしれません。可能であれば、異なる環境でテストしてみてください。
  2. 選択範囲に意図せず下線が適用される/されない

    • 原因
      • 選択範囲の誤り
        ユーザーが意図しない範囲を選択している可能性があります。
      • プログラム側の選択範囲管理の誤り
        QTextCursor を使用してプログラム的に選択範囲を操作している場合、その範囲が期待通りになっていない可能性があります。
      • カーソル位置の問題
        テキストが選択されていない状態で setFontUnderline(true) を呼び出すと、その後の入力から下線が適用されます。既存のテキストに下線を適用したい場合は、明示的にその範囲を選択する必要があります。
    • トラブルシューティング
      • 選択範囲の視覚的な確認
        ユーザーに選択範囲を明確に意識してもらうように促すか、プログラム側で選択範囲をハイライト表示するなどして確認しやすくします。
      • QTextCursor のデバッグ
        プログラムで選択範囲を操作している場合は、QTextCursorselectionStart()selectionEnd() の値を確認し、意図した範囲になっているかログ出力するなどしてデバッグします。
      • テキストが選択されているか確認
        下線を適用する前に、textCursor().hasSelection() でテキストが選択されているか確認し、必要に応じて selectAll() などで明示的に選択範囲を設定します。
  3. ボタンなどのUI要素と連携した際の問題

    • 原因
      • シグナルとスロットの接続ミス
        ボタンのクリックなどのシグナルが、setFontUnderline() スロットに正しく接続されていない。
      • タイミングの問題
        ボタンの状態や他のUI要素の状態が、setFontUnderline() が呼び出されるタイミングで期待通りになっていない。
      • 論理的なエラー
        下線を適用する条件が正しく判定されていない。
    • トラブルシューティング
      • シグナルとスロットの接続確認
        QObject::connect() が正しく記述されているか、シグナルの種類とスロットの引数が一致しているかなどを確認します。
      • デバッグ出力
        ボタンの状態や関連する変数の値をログ出力し、処理の流れが期待通りになっているか確認します。
      • 状態管理の確認
        下線を適用するかどうかの状態を管理する変数が正しく更新されているか確認します。
  • リッチテキストエディタの高度な機能(例えば、下線のスタイルや色を変更するなど)を実現するには、QTextCharFormat クラスを操作する必要があります。setFontUnderline() は、単純な下線のオン/オフを切り替えるための便利な関数です。
  • 下線の設定を切り替えるUI(例えば、下線ボタン)を作成する場合、ボタンの状態に応じて setFontUnderline(true) または setFontUnderline(false) を呼び出す必要があります。
  • setFontUnderline() は、現在のテキストフォーマットに下線の属性を設定する関数です。この関数を呼び出した時点でのカーソル位置または選択範囲に影響を与えます。


基本的な下線のオン・オフ

#include <QApplication>
#include <QTextEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QTextEdit *textEdit = new QTextEdit();
    QPushButton *underlineButton = new QPushButton("下線を引く");
    QPushButton *removeUnderlineButton = new QPushButton("下線を削除");

    layout->addWidget(textEdit);
    layout->addWidget(underlineButton);
    layout->addWidget(removeUnderlineButton);

    // 「下線を引く」ボタンがクリックされた時の処理
    QObject::connect(underlineButton, &QPushButton::clicked, [=]() {
        textEdit->setFontUnderline(true); // 選択中のテキストに下線を設定
    });

    // 「下線を削除」ボタンがクリックされた時の処理
    QObject::connect(removeUnderlineButton, &QPushButton::clicked, [=]() {
        textEdit->setFontUnderline(false); // 選択中のテキストから下線を削除
    });

    window.setLayout(layout);
    window.show();

    return app.exec();
}

この例では、QTextEdit と二つの QPushButton(「下線を引く」と「下線を削除」)を持つ簡単なGUIアプリケーションを作成しています。

  • 「下線を削除」ボタンがクリックされると、ラムダ式 [=]() { textEdit->setFontUnderline(false); }; が実行され、選択されているテキストの下線が解除されます。
  • 「下線を引く」ボタンがクリックされると、ラムダ式 [=]() { textEdit->setFontUnderline(true); }; が実行され、textEdit 内で現在選択されているテキストに下線が設定されます。もしテキストが選択されていなければ、以降に入力されるテキストに下線が適用されます。

トグルボタンによる下線の切り替え

#include <QApplication>
#include <QTextEdit>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QWidget>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QTextEdit *textEdit = new QTextEdit();
    QCheckBox *underlineCheckBox = new QCheckBox("下線");

    layout->addWidget(textEdit);
    layout->addWidget(underlineCheckBox);

    // チェックボックスの状態が変更された時の処理
    QObject::connect(underlineCheckBox, &QCheckBox::stateChanged, [=](int state) {
        if (state == Qt::Checked) {
            textEdit->setFontUnderline(true); // チェックが入ったら下線を設定
        } else {
            textEdit->setFontUnderline(false); // チェックが外れたら下線を削除
        }
    });

    window.setLayout(layout);
    window.show();

    return app.exec();
}

この例では、下線のオン・オフを切り替えるために QCheckBox を使用しています。

  • stateQt::Checked (チェックされている) であれば textEdit->setFontUnderline(true) を呼び出して下線を設定し、そうでなければ textEdit->setFontUnderline(false) を呼び出して下線を解除します。
  • QCheckBoxstateChanged シグナルに接続されたラムダ式では、チェックボックスの状態 (state) を確認しています。

テキストの特定の部分に下線を設定する (QTextCursor を使用)

#include <QApplication>
#include <QTextEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QTextCursor>
#include <QTextCharFormat>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QTextEdit *textEdit = new QTextEdit("これは下線が引かれるテキストです。");
    QPushButton *underlineButton = new QPushButton("特定の部分に下線を引く");

    layout->addWidget(textEdit);
    layout->addWidget(underlineButton);

    QObject::connect(underlineButton, &QPushButton::clicked, [=]() {
        QTextCursor cursor = textEdit->textCursor();
        cursor.setPosition(3); // 下線を開始する位置 (例: 「は」の次)
        cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 5); // 5文字選択 (例: 「下線が引か」)

        QTextCharFormat format;
        format.setFontUnderline(true);
        cursor.mergeCharFormat(format); // 選択範囲に下線フォーマットを適用
        textEdit->setTextCursor(cursor); // カーソルを戻す (必要に応じて)
    });

    window.setLayout(layout);
    window.show();

    return app.exec();
}

この例では、QTextCursor を使用して QTextEdit 内の特定の部分にプログラム的に下線を設定する方法を示しています。

  • 最後に、必要に応じて textEdit->setTextCursor(cursor) でカーソルを元の位置に戻します。
  • cursor.mergeCharFormat(format) で、作成した下線フォーマットを選択範囲に適用します。
  • QTextCharFormat オブジェクトを作成し、format.setFontUnderline(true) で下線を設定します。
  • cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, 5) で、現在の位置から右に5文字分の選択範囲を作成します (KeepAnchor は移動前の位置をアンカーとして保持し、選択範囲を拡張します)。
  • cursor.setPosition(3) でカーソルの開始位置を移動させます。
  • ボタンがクリックされると、まず textEdit の現在のカーソルを取得します。


QTextCharFormat を直接操作する

QTextCharFormat クラスは、テキストの文字属性(フォント、色、下線、太字など)を管理するためのクラスです。QTextCursor と組み合わせて使用することで、より細かく下線のスタイルを設定したり、特定の部分にのみ下線を適用したりできます。

#include <QApplication>
#include <QTextEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QTextCursor>
#include <QTextCharFormat>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QTextEdit *textEdit = new QTextEdit("これは下線スタイルを変更するテキストです。");
    QPushButton *underlineButton = new QPushButton("二重下線にする");

    layout->addWidget(textEdit);
    layout->addWidget(underlineButton);

    QObject::connect(underlineButton, &QPushButton::clicked, [=]() {
        QTextCursor cursor = textEdit->textCursor();
        cursor.select(QTextCursor::Document); // ドキュメント全体を選択

        QTextCharFormat format = cursor.charFormat();
        format.setFontUnderline(true);
        format.setUnderlineStyle(QFont::DoubleUnderline); // 二重下線を設定

        cursor.mergeCharFormat(format);
        textEdit->setTextCursor(cursor); // カーソルを戻す
    });

    window.setLayout(layout);
    window.show();

    return app.exec();
}

この例では、ボタンがクリックされると、QTextCursor でドキュメント全体を選択し、現在の文字フォーマットを取得します。次に、setFontUnderline(true) で下線を有効にし、setUnderlineStyle(QFont::DoubleUnderline) で下線のスタイルを二重線に設定しています。最後に、mergeCharFormat() でこの新しいフォーマットを選択範囲に適用します。QFont::SingleUnderlineQFont::DashUnderlineQFont::DotUnderline など、様々な下線スタイルを指定できます。

リッチテキスト形式 (HTMLなど) を使用する

QTextEdit はリッチテキスト形式(HTMLの一部を含む)をサポートしています。HTMLの <u> タグを使用することで、テキストに下線を設定できます。

#include <QApplication>
#include <QTextEdit>
#include <QVBoxLayout>
#include <QWidget>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QTextEdit *textEdit = new QTextEdit();
    textEdit->setHtml("これは<u>下線が引かれた</u>テキストです。");

    layout->addWidget(textEdit);
    window.setLayout(layout);
    window.show();

    return app.exec();
}

この方法では、setHtml() 関数に HTML 形式の文字列を渡すことで、<u> タグで囲まれた部分に下線が表示されます。より複雑なスタイルを適用したい場合は、HTML の <span> タグと CSS の text-decoration: underline; プロパティを組み合わせることもできます。

#include <QApplication>
#include <QTextEdit>
#include <QVBoxLayout>
#include <QWidget>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QTextEdit *textEdit = new QTextEdit();
    textEdit->setHtml("これは<span style=\"text-decoration: underline;\">下線が引かれた</span>テキストです。");

    layout->addWidget(textEdit);
    window.setLayout(layout);
    window.show();

    return app.exec();
}

スタイルシート (CSS) を使用する

QTextEdit はスタイルシートをある程度サポートしています。ただし、テキストの一部だけにスタイルを適用するには、リッチテキスト形式と組み合わせる必要があります。

#include <QApplication>
#include <QTextEdit>
#include <QVBoxLayout>
#include <QWidget>

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);
    QTextEdit *textEdit = new QTextEdit();
    textEdit->setHtml("<span class=\"underlined\">この部分に下線</span>が表示されます。");
    textEdit->setStyleSheet(".underlined { text-decoration: underline; }");

    layout->addWidget(textEdit);
    window.setLayout(layout);
    window.show();

    return app.exec();
}

この例では、HTML の <span> タグに class="underlined" を設定し、スタイルシートで .underlined クラスに対して text-decoration: underline; を指定しています。

  • スタイルシート (CSS): アプリケーション全体または特定のウィジェット内で一貫したスタイルを管理したい場合に有効ですが、QTextEdit でテキストの一部だけにスタイルを適用するには HTML との組み合わせが必要です。
  • リッチテキスト (HTML): 静的なテキストに下線を適用する場合や、他のリッチテキスト要素(太字、斜体など)と組み合わせて使用する場合に便利です。動的にテキストの内容を変更する場合は、setHtml() を再度呼び出す必要があります。
  • QTextCharFormat: 下線のスタイル(単線、二重線、点線など)を細かく制御したい場合や、テキストの特定の部分にプログラム的に複雑な書式を適用したい場合に適しています。
  • setFontUnderline(): 現在のカーソル位置または選択範囲に対して、単純な下線のオン・オフを切り替える場合に便利です。