Qtプログラミングで打ち消し線!QFont::setStrikeOut()徹底解説

2025-06-06

機能

この関数はブール値(trueまたはfalse)を引数として受け取ります。

  • setStrikeOut(false): フォントを使用して描画されるテキストから打ち消し線が削除されるように設定します(これがデフォルトの状態です)。
  • setStrikeOut(true): フォントを使用して描画されるテキストに打ち消し線が引かれるように設定します。
#include <QApplication>
#include <QLabel>
#include <QFont>

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

    QLabel label;
    QFont font = label.font(); // 現在のフォントを取得

    // 打ち消し線を有効にする
    font.setStrikeOut(true);
    label.setFont(font);
    label.setText("これは打ち消し線のあるテキストです。");
    label.show();

    // 別のラベルで打ち消し線を無効にする例
    QLabel label2;
    QFont font2 = label2.font();
    font2.setStrikeOut(false); // 明示的に無効にする(デフォルトと同じ)
    label2.setFont(font2);
    label2.setText("これは通常のテキストです。");
    label2.move(0, 50); // 位置をずらして表示
    label2.show();

    return app.exec();
}
  • 実際に画面にテキストを描画する際には、QPainterなどを使用して、このQFontオブジェクトを適用します。
  • この設定は、そのQFontオブジェクトが適用されるすべてのテキストに影響します。
  • QFontオブジェクトは、テキストのフォントファミリー、サイズ、太さ、イタリック、下線、上線など、様々な属性を設定するために使用されます。setStrikeOut()はその属性の一つです。


QFont::setStrikeOut()はフォントの属性を設定するだけであり、それ自体がクラッシュしたり、コンパイルエラーを直接引き起こすことは稀です。しかし、以下のような状況で期待通りの結果が得られないことがあります。

打ち消し線が表示されない

最も一般的な問題は、setStrikeOut(true)を設定しても打ち消し線が表示されないケースです。

原因とトラブルシューティング

  • QPainterでの描画順序の問題

    • カスタムペイントイベント(paintEvent())でQPainterを使用してテキストを描画している場合、打ち消し線が他の描画要素によって隠されていないか確認してください。
    • 解決策
      描画順序を調整するか、QPainterのクリッピング設定を確認します。
  • フォント自体が打ち消し線をサポートしていない、または表示に問題がある

    • ごく稀に、特定のフォントやプラットフォームのフォントレンダリングエンジンによっては、打ち消し線の表示に問題がある場合があります。特に、非常に珍しいフォントや古いシステムフォントなどで起こりえます。
    • 解決策
      別の一般的なフォント(例: Arial, Meiryo UIなど)で試してみて、問題が再現するかどうかを確認します。
  • スタイルシート(Style Sheet)による上書き

    • Qtのスタイルシートは、ウィジェットのプロパティ(フォントを含む)を非常に強力に制御します。もしウィジェットにスタイルシートが適用されている場合、C++コードでsetFont()を使って設定したフォント属性(打ち消し線を含む)がスタイルシートの設定によって上書きされることがあります。
    • 例:
      QLabel *label = new QLabel("テキスト");
      label->setStyleSheet("QLabel { font-family: 'Arial'; font-size: 16px; }"); // スタイルシート
      QFont font = label->font();
      font.setStrikeOut(true);
      label->setFont(font); // スタイルシートに上書きされる可能性
      
    • 解決策
      • スタイルシートでフォント属性(text-decoration: line-through;)を設定してみてください。
        QLabel {
            text-decoration: line-through;
        }
        
      • 特定のウィジェットに対してのみスタイルシートを使用する場合は、setObjectName()とセレクタを使用します。
        QLabel *label = new QLabel("テキスト");
        label->setObjectName("myStrikeOutLabel");
        label->setStyleSheet("QLabel#myStrikeOutLabel { text-decoration: line-through; }");
        
      • C++コードでのsetFont()設定を優先したい場合は、スタイルシートの該当するフォントプロパティを削除するか、より具体的なセレクタを使ってスタイルシートの適用範囲を限定します。
    • QFontオブジェクトを作成し、setStrikeOut(true)を呼び出しても、そのフォントを実際にウィジェット(QLabelQPushButtonなど)やQPainterに設定し直さないと効果はありません。
    • 例:
      QLabel label;
      QFont font = label.font(); // 現在のフォントを取得
      font.setStrikeOut(true);   // ここで設定
      // label.setFont(font);    // これがないと反映されない!
      label.setText("テスト");
      
    • 解決策
      setFont()QPainter::setFont()など、適切なメソッドで更新されたQFontオブジェクトを適用してください。

フォントのコピーと共有に関する誤解

QFontオブジェクトは値セマンティクス(value semantics)を持ちます。これは、QFontオブジェクトをコピーすると、独立した新しいフォントオブジェクトが作成されることを意味します。

原因とトラブルシューティング

  • 一時オブジェクトの誤用

        QLabel label;
        label.font().setStrikeOut(true); // これは一時オブジェクトに設定しているため、効果がない
    
    • label.font()QFontのコピーを一時的に作成します。その一時オブジェクトに対してsetStrikeOut(true)を呼び出しても、その変更はlabelの実際のフォントには反映されません。
    • 解決策
      必ずQFontオブジェクトを変数に保持し、変更を加えてからsetFont()で設定してください。
  • ウィジェットのフォントを直接変更していない

        QLabel label;
        QFont font = label.font(); // label.font()はQLabelのフォントのコピーを返す
        font.setStrikeOut(true);   // ここでfontを修正しても、labelのフォントは変更されない
        // 正しくlabel.setFont(font); を呼び出す必要がある
    
    • 解決策
      変更したQFontオブジェクトを必ず元のウィジェットやQPainterに設定し直してください。

setStrikeOut()自体とは直接関係ありませんが、フォント全般でよくあるトラブルとして、以下の点も考慮すると良いでしょう。

  • Qtバージョン間の挙動の違い
    古いQtバージョンと新しいQtバージョンでは、フォントレンダリングの挙動やスタイルシートの解釈にわずかな違いがある可能性があります。特定のバージョンで問題が発生する場合は、Qtの公式ドキュメントや変更履歴を確認すると良いでしょう。
  • フォントが見つからない
    指定したフォントファミリー(例: QFont("MyCustomFont", 10))がシステムにインストールされていない場合、Qtは代替フォントを使用します。この場合、打ち消し線は表示されるかもしれませんが、他のフォント属性が意図通りでない可能性があります。QFontInfoを使用して、実際に使用されているフォントの情報を確認できます。
  • QApplicationインスタンスがない
    QFontを使用する前にQApplicationインスタンスが作成されている必要があります。これはQtアプリケーションの基本ですが、まれに見落とされることがあります。


QFont::setStrikeOut()は、テキストに打ち消し線(strike-out line)を引くかどうかを制御するために使用されます。ここでは、異なるシナリオでの使用例を示します。

例1: QLabel のテキストに打ち消し線を引く基本的な例

最も一般的な使用例は、QLabelなどのウィジェットに表示されるテキストに打ち消し線を適用することです。

#include <QApplication>
#include <QLabel>
#include <QFont>
#include <QVBoxLayout> // レイアウト管理のため

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

    // メインウィンドウとレイアウトの設定
    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);

    // 1. 通常のテキストを持つQLabel
    QLabel *normalLabel = new QLabel("これは通常のテキストです。");
    layout->addWidget(normalLabel);

    // 2. 打ち消し線のあるテキストを持つQLabel
    QLabel *strikeOutLabel = new QLabel("これは打ち消し線のあるテキストです。");

    // QLabelの現在のフォントを取得(コピーされる)
    QFont font = strikeOutLabel->font();

    // 打ち消し線を有効にする
    font.setStrikeOut(true);

    // 変更したフォントをQLabelに設定し直す
    strikeOutLabel->setFont(font);

    layout->addWidget(strikeOutLabel);

    // 3. 太字と打ち消し線のあるテキストを持つQLabel
    QLabel *boldStrikeOutLabel = new QLabel("これは太字で打ち消し線のあるテキストです。");
    QFont boldFont = boldStrikeOutLabel->font();
    boldFont.setBold(true);      // 太字を設定
    boldFont.setStrikeOut(true); // 打ち消し線を設定
    boldStrikeOutLabel->setFont(boldFont);
    layout->addWidget(boldStrikeOutLabel);

    window.setWindowTitle("QFont::setStrikeOut() 例");
    window.show();

    return app.exec();
}

解説

  1. QLabelfont()メソッドを使って、現在のフォントのコピーを取得します。
  2. 取得したQFontオブジェクトのsetStrikeOut(true)を呼び出して、打ち消し線を有効にします。
  3. 変更を加えたQFontオブジェクトを、QLabelsetFont()メソッドを使って再度設定します。これを忘れると、変更は反映されません。
  4. 他のフォント属性(setBold()など)と組み合わせて使用することも可能です。

例2: QPainter を使用してカスタムウィジェットに打ち消し線のあるテキストを描画する

QPainterを使用して、ウィジェットのpaintEvent内でテキストを描画する場合にもQFont::setStrikeOut()を使用できます。

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QFont>

class CustomPaintWidget : public QWidget
{
public:
    CustomPaintWidget(QWidget *parent = nullptr) : QWidget(parent)
    {
        setMinimumSize(300, 150);
    }

protected:
    void paintEvent(QPaintEvent *event) override
    {
        Q_UNUSED(event);

        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing); // アンチエイリアスを有効にする

        // 1. 通常のテキストの描画
        QFont normalFont = painter.font(); // 現在のペインターのフォントを取得
        painter.setFont(normalFont);
        painter.drawText(10, 30, "QPainter: 通常のテキスト");

        // 2. 打ち消し線のあるテキストの描画
        QFont strikeOutFont = painter.font(); // 現在のペインターのフォントを取得
        strikeOutFont.setStrikeOut(true);     // 打ち消し線を有効にする
        painter.setFont(strikeOutFont);       // ペインターに新しいフォントを設定
        painter.drawText(10, 60, "QPainter: 打ち消し線のあるテキスト");

        // 3. サイズを変更して打ち消し線のあるテキストの描画
        QFont largeStrikeOutFont = painter.font();
        largeStrikeOutFont.setPointSize(18); // フォントサイズを変更
        largeStrikeOutFont.setStrikeOut(true);
        painter.setFont(largeStrikeOutFont);
        painter.drawText(10, 100, "QPainter: 大きくて打ち消し線のあるテキスト");
    }
};

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

    CustomPaintWidget widget;
    widget.setWindowTitle("QPainterでのQFont::setStrikeOut() 例");
    widget.show();

    return app.exec();
}

解説

  1. カスタムウィジェットを作成し、paintEventをオーバーライドします。
  2. QPainterオブジェクトを初期化します。
  3. painter.font()で現在のフォントを取得し、setStrikeOut(true)で打ち消し線を有効にします。
  4. painter.setFont()で変更したフォントをQPainterに設定し、その後drawText()でテキストを描画します。

例3: スタイルシート(CSS)で打ち消し線を設定する(QFont::setStrikeOut()の代替)

Qtでは、CSSライクなスタイルシートを使ってウィジェットの見た目を制御することもできます。打ち消し線もスタイルシートで設定可能です。この場合、C++コードでQFont::setStrikeOut()を呼び出す必要はありません。

#include <QApplication>
#include <QLabel>
#include <QVBoxLayout>

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

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);

    QLabel *label1 = new QLabel("これはスタイルシートで打ち消し線が設定されたテキストです。");
    // text-decorationプロパティをline-throughに設定
    label1->setStyleSheet("QLabel { text-decoration: line-through; }");
    layout->addWidget(label1);

    QLabel *label2 = new QLabel("特定のIDを持つラベルにのみ打ち消し線を適用。");
    label2->setObjectName("myStrikeOutLabel"); // オブジェクトIDを設定
    // オブジェクトIDを使って特定のラベルにスタイルを適用
    window.setStyleSheet("QLabel#myStrikeOutLabel { text-decoration: line-through; color: red; font-size: 14px; }");
    layout->addWidget(label2);

    // QFont::setStrikeOut()とスタイルシートが競合する例 (注意が必要)
    QLabel *mixedLabel = new QLabel("C++コードとスタイルシートの競合の例");
    QFont font = mixedLabel->font();
    font.setStrikeOut(true); // C++コードで打ち消し線を設定
    mixedLabel->setFont(font);
    // スタイルシートでtext-decorationが設定されていない場合、C++のsetFontが優先される
    // もしスタイルシートでtext-decorationが設定された場合、スタイルシートが優先される可能性が高い
    mixedLabel->setStyleSheet("QLabel { color: blue; }"); // 打ち消し線以外を設定
    // mixedLabel->setStyleSheet("QLabel { text-decoration: none; }"); // これだとC++の打ち消し線が消される
    layout->addWidget(mixedLabel);


    window.setWindowTitle("スタイルシートでの打ち消し線 例");
    window.show();

    return app.exec();
}
  1. スタイルシートでは、text-decorationプロパティをline-throughに設定することで、打ち消し線を適用できます。
  2. text-decoration: none;を設定すると、打ち消し線(および下線、上線)を無効にできます。
  3. C++コードのsetFont()とスタイルシートが競合した場合、通常はより具体的なルールを持つスタイルシートが優先されます。どちらか一方の方法に統一することをお勧めします。


Qtでテキストに打ち消し線(strike-out line)を引く方法は、主に以下の2つがQFont::setStrikeOut()の代替として考えられます。

  1. スタイルシート(CSS)を使用する方法
  2. HTML/リッチテキストを使用する方法

それぞれ詳しく見ていきましょう。

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

Qtのスタイルシートは、HTMLのCSSに似た構文でウィジェットの見た目をカスタマイズするための強力なメカニズムです。text-decorationプロパティを使って、打ち消し線を簡単に設定できます。

特徴

  • 優先順位
    C++コードでsetFont()を使って設定したフォント属性よりも、スタイルシートのルールが優先される場合があります(特にtext-decorationのような明示的な指定の場合)。
  • 動的な変更
    実行時にスタイルシートを切り替えることで、アプリケーションのテーマを変更するといったことが容易です。
  • 柔軟性
    アプリケーション全体、特定のウィジェットクラス、特定のオブジェクト名を持つウィジェットなど、様々な粒度でスタイルを適用できます。
  • 宣言的
    コードから見た目の設定が分離されるため、管理がしやすいです。

コード例

#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>

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

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);

    // 例1: QLabel にスタイルシートで打ち消し線を設定
    QLabel *label1 = new QLabel("これはスタイルシートで打ち消し線のあるテキストです。");
    label1->setStyleSheet("QLabel { text-decoration: line-through; color: blue; font-size: 16px; }");
    layout->addWidget(label1);

    // 例2: QPushButton のテキストにスタイルシートで打ち消し線を設定
    QPushButton *button1 = new QPushButton("キャンセル済み");
    button1->setStyleSheet("QPushButton { text-decoration: line-through; }");
    layout->addWidget(button1);

    // 例3: 特定のオブジェクト名を持つウィジェットにのみ適用
    QLabel *label2 = new QLabel("特定IDのラベル");
    label2->setObjectName("deletedItem"); // オブジェクトIDを設定
    // アプリケーション全体または親ウィジェットにスタイルシートを設定
    window.setStyleSheet("QLabel#deletedItem { text-decoration: line-through; font-weight: bold; }");
    layout->addWidget(label2);

    window.setWindowTitle("スタイルシートの例 (text-decoration: line-through)");
    window.show();

    return app.exec();
}

CSSプロパティ

  • text-decoration: overline;:上線を適用します。
  • text-decoration: underline;:下線を適用します。
  • text-decoration: none;:打ち消し線、下線、上線をすべて削除します。
  • text-decoration: line-through;:打ち消し線を適用します。

HTML/リッチテキストを使用する方法

Qtの多くのウィジェット(QLabelQTextEditQTextBrowserなど)は、テキストをHTML形式で解釈し表示する機能を持っています。これにより、HTMLタグを使って打ち消し線を表現できます。

特徴

  • 他のHTMLタグとの組み合わせ
    色、フォントサイズ、太字、イタリックなど、他のHTMLタグと組み合わせて複雑なテキスト表現が可能です。
  • コンテンツ内での柔軟性
    テキストの一部にのみ打ち消し線を適用したい場合に便利です。
  • シンプル
    HTMLの<s>または<del>タグを使うだけで簡単に設定できます。

コード例

#include <QApplication>
#include <QLabel>
#include <QTextEdit>
#include <QVBoxLayout>

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

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);

    // 例1: QLabel で HTML を使用
    QLabel *label1 = new QLabel();
    // <s> または <del> タグを使用
    label1->setText("これは <s>HTMLの打ち消し線</s> を使ったテキストです。");
    // label1->setText("これは <del>HTMLの打ち消し線</del> を使ったテキストです。"); // 同じ効果
    layout->addWidget(label1);

    // 例2: QLabel で一部にHTMLを適用
    QLabel *label2 = new QLabel();
    label2->setText("今日の特別価格: <span style=\"color: gray;\"><s>$100</s></span> <span style=\"color: red; font-weight: bold;\">$75</span>");
    layout->addWidget(label2);

    // 例3: QTextEdit で HTML を使用
    QTextEdit *textEdit = new QTextEdit();
    textEdit->setHtml("<h1>商品リスト</h1><ul><li>商品A: <s>¥1000</s> <span style=\"color: green;\">¥800</span></li><li>商品B: <del>在庫なし</del></li><li>商品C: ¥1500</li></ul>");
    textEdit->setReadOnly(true); // 読み取り専用にする
    layout->addWidget(textEdit);


    window.setWindowTitle("HTML/リッチテキストの例 (<s> / <del>)");
    window.show();

    return app.exec();
}

HTMLタグ

  • <del>テキスト</del>: 打ち消し線を引きます(削除されたテキストを示す意味合い)。
  • <s>テキスト</s>: 打ち消し線を引きます。

どちらの代替方法を選ぶべきか?

  • テキストコンテンツの一部にのみ打ち消し線を適用したい場合や、複雑なリッチテキスト表現が必要な場合は、HTML/リッチテキストが便利です。
  • ウィジェット全体の見た目を統一的に変更したい場合や、UIのデザインをC++コードから分離したい場合は、スタイルシートが非常に強力で推奨されます。

QFont::setStrikeOut()は、C++コードでフォントオブジェクトを直接操作する最も直接的な方法ですが、上記2つの代替方法は、より柔軟性や表現力を提供することが多いです。状況に応じて最適な方法を選択してください。 QFont::setStrikeOut()はQtでテキストに打ち消し線を引くための標準的な方法ですが、状況によっては別の代替手段を検討することもあります。

QFont::setStrikeOut()QFontオブジェクトの直接的なプロパティであり、C++コードでフォントを設定する際には非常に便利です。しかし、異なる要件やフレームワークを使用している場合、他の方法が適していることがあります。

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

これは、Qtウィジェットの外観をカスタマイズするための非常に強力で柔軟な方法です。CSSのtext-decorationプロパティを使って打ち消し線を設定できます。

特徴

  • 特定のウィジェットに適用
    オブジェクト名やクラスセレクタを使用して、特定のウィジェットにのみスタイルを適用できます。
  • 動的な変更が容易
    実行時にスタイルシートを切り替えることで、アプリケーション全体のテーマを簡単に変更できます。
  • 分離(Separation of Concerns)
    UIのレイアウトやロジックからスタイリングを分離できます。
  • 宣言的(Declarative)
    コードに直接フォント設定を記述する代わりに、スタイルシートファイルまたは文字列として定義します。

コード例

#include <QApplication>
#include <QLabel>
#include <QVBoxLayout>

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

    QWidget window;
    QVBoxLayout *layout = new QVBoxLayout(&window);

    QLabel *label1 = new QLabel("これはスタイルシートによる打ち消し線です。");
    // QLabelに直接スタイルシートを設定
    label1->setStyleSheet("QLabel { text-decoration: line-through; color: red; }");
    layout->addWidget(label1);

    QLabel *label2 = new QLabel("特定のIDを持つラベル");
    label2->setObjectName("mySpecialLabel"); // オブジェクト名を指定
    // ウィンドウ全体にスタイルシートを設定し、特定のオブジェクトに適用
    window.setStyleSheet(
        "QLabel#mySpecialLabel {"
        "   text-decoration: line-through;"
        "   font-size: 16px;"
        "   font-weight: bold;"
        "   color: blue;"
        "}"
    );
    layout->addWidget(label2);

    window.setWindowTitle("スタイルシートの例");
    window.show();

    return app.exec();
}

利点

  • デザインとコードの分離
    デザイナーがUIの外観を、開発者がロジックをそれぞれ担当しやすくなります。
  • 管理のしやすさ
    スタイルを一つの場所に集約できます。
  • 柔軟性
    複雑なスタイルを簡単に適用できます。

欠点

  • 競合
    C++コードでのQFont::setStrikeOut()とスタイルシートが同時に適用された場合、スタイルシートのルールが優先されることが多いです。
  • パフォーマンス
    C++コードで直接フォントを設定するよりも、わずかにオーバーヘッドがある可能性があります(通常は無視できるレベル)。

QML の Text 要素と HTML/StyledText フォーマット

Qt Quick (QML) を使用している場合、Text要素内でHTMLタグまたはStyledTextフォーマットを使用して打ち消し線を表現できます。

特徴

  • StyledText
    より軽量なStyledTextフォーマットでも基本的なスタイリングが可能です。
  • HTMLサブセット
    Text要素はHTMLのサブセットをサポートしており、<u> (下線), <b> (太字), <i> (イタリック) などと同様に、<s> または <strike> タグで打ち消し線を表現できます。
  • QMLネイティブ
    QMLの構文で直接テキストをスタイルできます。

コード例 (QML)

import QtQuick 2.15
import QtQuick.Window 2.15

Window {
    width: 400
    height: 200
    visible: true
    title: "QML Text Strikethrough Example"

    Column {
        spacing: 20
        anchors.centerIn: parent

        // HTMLタグを使用
        Text {
            text: "これは<b>HTMLタグ</b>で<strike>打ち消し線</strike>のあるテキストです。"
            font.pointSize: 14
            textFormat: Text.RichText // HTMLタグを解釈するために必要
        }

        // 別の例 (<s>タグも使える)
        Text {
            text: "<s>別の打ち消し線</s>の例です。"
            font.pointSize: 16
            color: "green"
            textFormat: Text.RichText
        }

        // スタイルシートと類似のtext-decorationプロパティはQML Text要素のfontプロパティにはない
        // が、Text.StyledTextやText.RichTextを使うことで同じ効果が得られる

        // QML Text要素のtextFormatプロパティについて補足
        // Text.AutoText: 自動でHTML/StyledTextかを判断 (デフォルト)
        // Text.PlainText: 単純なテキスト
        // Text.StyledText: 軽量なHTMLサブセット (効率的)
        // Text.RichText: より完全なHTMLサブセット (高機能)
    }
}

解説

  1. Text要素のtextFormatプロパティをText.RichTextに設定することが重要です。これにより、QMLエンジンがHTMLタグを解釈してテキストをレンダリングします。
  2. <strike> または <s> タグで囲まれたテキストに打ち消し線が適用されます。

利点

  • HTMLの知識を活用
    Web開発の経験がある人には馴染みやすいです。
  • QMLとの親和性
    QMLアプリケーションでは自然な方法です。

欠点

  • HTMLサブセットの制限
    すべてのHTML/CSSプロパティがサポートされているわけではありません。
  • HTMLパーシングのオーバーヘッド
    非常に複雑なHTMLを使用する場合、パフォーマンスに影響を与える可能性があります。

カスタムペイントイベントでの直接描画

これはあまり一般的ではありませんが、特定の要件がある場合や、QTextDocumentなどの高レベルなテキストレンダリング機能を使わずに、ピクセルレベルで完全に制御したい場合に採用されます。

アプローチ

  1. 通常のテキストをQPainter::drawText()で描画します。
  2. そのテキストの描画領域(QFontMetricsを使って取得)を計算します。
  3. 計算した領域に基づいて、QPainter::drawLine()で打ち消し線を直接描画します。線の位置や太さ、色を完全に制御できます。

コード例

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QFont>
#include <QFontMetrics>

class CustomStrikethroughWidget : public QWidget
{
public:
    CustomStrikethroughWidget(QWidget *parent = nullptr) : QWidget(parent)
    {
        setMinimumSize(400, 200);
    }

protected:
    void paintEvent(QPaintEvent *event) override
    {
        Q_UNUSED(event);

        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);

        QString text = "これはカスタム描画の打ち消し線です。";
        QFont font("Arial", 20);
        painter.setFont(font);

        // テキストの描画領域を計算
        QFontMetrics fm(font);
        // baselineの位置を取得 (テキストの基準線)
        int textX = 50;
        int textY = 80;
        // テキストの幅
        int textWidth = fm.horizontalAdvance(text);
        // テキストの高さ
        int textHeight = fm.height();

        // テキストを描画
        painter.drawText(textX, textY, text);

        // 打ち消し線の位置を計算
        // 通常、打ち消し線はテキストの半分あたりの高さに引かれる
        // 例えば、baselineから少し上に描画する
        int strikeOutY = textY - fm.descent() - (fm.ascent() - fm.descent()) / 2; // おおよそ中央
        // または、特定のピクセルオフセットで調整
        // int strikeOutY = textY - fm.ascent() / 2 + 2; // 調整例

        // 打ち消し線の色と太さを設定
        QPen pen(Qt::red); // 赤い線
        pen.setWidth(2);   // 太さ2ピクセル
        painter.setPen(pen);

        // 打ち消し線を描画
        painter.drawLine(textX, strikeOutY, textX + textWidth, strikeOutY);

        // 別のテキストと打ち消し線
        QString text2 = "もう一つの例";
        QFont font2("Times New Roman", 18);
        painter.setFont(font2);
        QFontMetrics fm2(font2);

        int text2X = 50;
        int text2Y = 150;
        int text2Width = fm2.horizontalAdvance(text2);

        painter.drawText(text2X, text2Y, text2);

        QPen pen2(Qt::darkGreen);
        pen2.setWidth(1);
        painter.setPen(pen2);
        int strikeOut2Y = text2Y - fm2.descent() - (fm2.ascent() - fm2.descent()) / 2;
        painter.drawLine(text2X, strikeOut2Y, text2X + text2Width, strikeOut2Y);
    }
};

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

    CustomStrikethroughWidget widget;
    widget.setWindowTitle("カスタム描画の打ち消し線");
    widget.show();

    return app.exec();
}

利点

  • 特殊な効果
    標準のsetStrikeOut()では不可能な、より複雑なカスタム描画(二重線、点線など)が可能です。
  • 最大の制御
    線の位置、太さ、色などを完全に制御できます。
  • 国際化/多言語対応
    テキストの描画方向(右から左など)や複雑なスクリプトに対応する際には、さらに複雑な計算が必要になります。
  • メンテナンス
    テキストの変更やフォントの変更があった場合に、線の位置計算を再調整する必要がある場合があります。
  • 複雑性
    自分で描画ロジックを実装する必要があり、コード量が増えます。