QFont::setStretch()

2025-06-06

  • 注意点:

    • setStretch()は、常にすべてのフォントで期待通りに機能するとは限りません。フォントの種類やOSのレンダリングエンジンによっては、効果が限定的であったり、見た目が悪くなる場合があります。特にビットマップフォントの場合、文字間隔は広がるものの文字自体は拡大されないなどの現象が起こることがあります。
    • フォントの伸縮度は、通常、QFont オブジェクトを作成した後、そのフォントを QPainterQWidget に設定する前に呼び出します。
  • 使用例:

    #include <QApplication>
    #include <QLabel>
    #include <QFont>
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
    
        QLabel label;
        label.setText("Qt Font Stretch Example");
    
        QFont font = label.font(); // 現在のフォントを取得
    
        // フォントの伸縮度を設定
        // 例えば、標準の1.5倍の幅にする
        font.setStretch(150);
        // または、定義済みの値を使用
        // font.setStretch(QFont::Expanded);
    
        label.setFont(font); // 設定したフォントをラベルに適用
    
        label.show();
    
        return app.exec();
    }
    
  • QFont::Stretch 列挙型: Qtには、あらかじめ定義されたストレッチ値が QFont::Stretch 列挙型として提供されています。これらを使用すると、一般的な伸縮度を簡単に設定できます。

    • QFont::UltraCondensed (50)
    • QFont::ExtraCondensed (62)
    • QFont::Condensed (75)
    • QFont::SemiCondensed (87)
    • QFont::Unstretched (100)
    • QFont::SemiExpanded (112)
    • QFont::Expanded (125)
    • QFont::ExtraExpanded (150)
    • QFont::UltraExpanded (200)
  • 引数: setStretch()は整数値の factor を引数として取ります。

    • 100が標準の(伸長されていない)フォントの幅を表します。
    • 100より小さい値を設定すると、フォントが圧縮されて細くなります。例えば、50を設定すると、標準の半分の幅になります。
    • 100より大きい値を設定すると、フォントが拡張されて幅広になります。例えば、200を設定すると、標準の2倍の幅になります。
  • 機能: setStretch()は、フォントの文字の幅を、元のフォントの幅に対する割合(パーセンテージ)で設定します。これにより、文字をより細くしたり、より幅広にしたりすることができます。



視覚的な効果がない、または期待通りではない

  • 原因とトラブルシューティング:
    • フォント自体の制限: すべてのフォントが setStretch()による伸縮をサポートしているわけではありません。特に、ビットマップフォントや、もともと伸縮を想定していない一部のフォントでは、文字自体が伸縮せず、単に文字間隔が広がるだけ、または全く変化しないことがあります。
      • 対策: 別のフォント(特にTrueTypeやOpenTypeなどのスケーラブルなフォント)を試してみてください。
    • ポイントサイズによる制限: 特定のフォント(特にサイズの大きいフォント、例: 48pt以上)では、setStretch()がうまく機能しないという報告があります。これは、フォントレンダリングエンジンの内部的な制約による可能性があります。
      • 対策: 大きいフォントサイズを使用している場合は、より小さいサイズで試すか、後述のQPaintersetTransform()を使う方法を検討してください。
    • 変更の適用忘れ: QFontオブジェクトのsetStretch()を呼び出しただけでは、UIに表示されるフォントは更新されません。変更したQFontオブジェクトを、QLabelQTextEditなどのウィジェット、またはQPainter再設定する必要があります。
      // 悪い例: フォントを設定し直していない
      // QFont font = myLabel->font();
      // font.setStretch(200);
      
      // 良い例: 変更したフォントを適用
      QFont font = myLabel->font();
      font.setStretch(200);
      myLabel->setFont(font); // これが重要!
      
    • QFontInfoとの混同: QFontInfoは、実際にシステムが選択したフォントの属性情報を提供します。QFontInfoは、QFontオブジェクトの属性を変更しても自動的には更新されません。setStretch()を呼び出した後にQFontInfoを作成してその値を参照するようにしてください。
      QFont font("Arial", 12);
      font.setStretch(200);
      QFontInfo info(font);
      qDebug() << "Actual stretch:" << info.stretch(); // 設定したstretch値が反映されているか確認
      
  • 問題: setStretch()を呼び出しても、フォントの見た目が変わらない、または設定した伸縮度が反映されていないように見える。

レイアウトの問題

  • 原因とトラブルシューティング:
    • ウィジェットのサイズ計算: 通常のウィジェットは、フォントの変更に応じて自動的にサイズを調整しようとしますが、複雑なレイアウトや固定サイズを設定している場合は、意図しない見た目になることがあります。
      • 対策:
        • QLabelなどのテキストを表示するウィジェットでadjustSize()を呼び出して、内容に合わせてサイズを調整させる。
        • QFontMetricsを使用して、伸縮後のテキストの正確な幅と高さを計算し、それに基づいてウィジェットのサイズやレイアウトを調整する。
        • レイアウトマネージャー(QVBoxLayout, QHBoxLayout, QGridLayoutなど)を使用している場合は、自動的にサイズ調整が行われることが多いですが、setSizePolicy()を適切に設定することも考慮してください。
  • 問題: フォントを伸縮させると、テキストの幅が変わるため、ウィジェットのレイアウトが崩れる。

パフォーマンスの問題

  • 原因とトラブルシューティング:
    • フォントレンダリングの負荷: フォントの伸縮は、OSやQtのグラフィックシステムに負荷をかける処理です。特に、GPUアクセラレーションが十分に活用されない環境や、複雑なフォントを使用している場合に顕著になります。
      • 対策:
        • パフォーマンスが重要な場所では、setStretch()の使用を最小限に抑える。
        • 事前に伸縮したフォントをQFontオブジェクトとして用意しておき、必要に応じて切り替えることで、頻繁なフォント生成を避ける。
        • 非常に動的な伸縮が必要な場合は、QPaintersetTransform()を使用して描画時にスケーリングを行うことも検討できます。これはフォント自体を伸縮させるのではなく、描画コンテキストをスケーリングするため、より柔軟な制御が可能ですが、ピクセルパーフェクトな描画が難しくなる場合があります。
  • 問題: 多くのテキストや頻繁なフォント変更でsetStretch()を使用すると、アプリケーションのパフォーマンスが低下する。

特定のプラットフォームやOSでの差異

  • 原因とトラブルシューティング:
    • フォントレンダリングエンジンの違い: OSごとにフォントのレンダリング方法や利用可能なフォント情報が異なります。Qtはこれらの違いを抽象化しようとしますが、完全に吸収できるわけではありません。
      • 対策:
        • 異なるOSでアプリケーションをテストし、互換性の問題がないか確認する。
        • 特定のフォントや伸縮度で問題が発生する場合は、代替フォントや、setStretch()以外の描画方法(QPaintersetTransform()など)を検討する。
  • 問題: あるOSではsetStretch()がうまく機能するが、別のOSでは効果がない、または見た目が異なる。
  • 原因とトラブルシューティング:
    • QTextCharFormatの使用: QTextDocument内のテキストにフォント属性を適用する場合は、QFontを直接ウィジェットに設定するのではなく、QTextCharFormatを介して行います。QTextCharFormatにもsetFontStretch()関数があります。
      QTextCursor cursor = textEdit->textCursor();
      QTextCharFormat format;
      format.setFontStretch(150); // QTextCharFormatで伸縮度を設定
      cursor.mergeCharFormat(format);
      // または、 QTextCursor::setCharFormat() を使用
      
  • 問題: QTextEditなどのリッチテキスト表示でsetStretch()を使用しようとすると、期待通りに機能しない。


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);

    // 標準のフォント
    QLabel *label1 = new QLabel("標準のフォント (Unstretched)");
    QFont font1 = label1->font();
    font1.setPointSize(20);
    label1->setFont(font1);
    layout->addWidget(label1);

    // 拡張されたフォント (UltraExpanded)
    QLabel *label2 = new QLabel("拡張されたフォント (UltraExpanded)");
    QFont font2 = label2->font();
    font2.setPointSize(20);
    font2.setStretch(QFont::UltraExpanded); // 200% に拡張
    label2->setFont(font2);
    layout->addWidget(label2);

    // 圧縮されたフォント (Condensed)
    QLabel *label3 = new QLabel("圧縮されたフォント (Condensed)");
    QFont font3 = label3->font();
    font3.setPointSize(20);
    font3.setStretch(QFont::Condensed); // 75% に圧縮
    label3->setFont(font3);
    layout->addWidget(label3);

    // 数値で直接指定する例 (150%)
    QLabel *label4 = new QLabel("数値で指定したフォント (150%)");
    QFont font4 = label4->font();
    font4.setPointSize(20);
    font4.setStretch(150); // 150% に拡張
    label4->setFont(font4);
    layout->addWidget(label4);

    window.setWindowTitle("QFont::setStretch() Example");
    window.show();

    return app.exec();
}

このコードでは、QLabel を複数作成し、それぞれ異なる setStretch() 値を設定した QFont を適用しています。QFont::Unstretched (100)、QFont::UltraExpanded (200)、QFont::Condensed (75) といった定義済みの列挙値や、任意の整数値 (150) を使用して伸縮度を設定している点がポイントです。

QPainter を使用してカスタム描画する

QWidgetpaintEvent などで QPainter を使用してテキストを描画する場合にも、QFont::setStretch() を適用できます。

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

class CustomPaintWidget : public QWidget {
public:
    CustomPaintWidget(QWidget *parent = nullptr) : QWidget(parent) {
        setWindowTitle("QPainter with QFont::setStretch()");
        setFixedSize(400, 300);
    }

protected:
    void paintEvent(QPaintEvent *event) override {
        Q_UNUSED(event);
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);

        // 標準のフォント
        QFont font1("Arial", 24);
        painter.setFont(font1);
        painter.drawText(20, 50, "Standard Font");

        // 拡張されたフォント
        QFont font2("Arial", 24);
        font2.setStretch(QFont::Expanded); // 125%
        painter.setFont(font2);
        painter.drawText(20, 100, "Expanded Font");

        // 圧縮されたフォント
        QFont font3("Arial", 24);
        font3.setStretch(QFont::SemiCondensed); // 87%
        painter.setFont(font3);
        painter.drawText(20, 150, "Semi-Condensed Font");

        // 極端に拡張されたフォント
        QFont font4("Arial", 24);
        font4.setStretch(250); // 250%
        painter.setFont(font4);
        painter.drawText(20, 200, "Very Wide Font");
    }
};

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

    CustomPaintWidget widget;
    widget.show();

    return app.exec();
}

QPaintersetFont() メソッドを使って、描画する前にフォントを設定しています。これにより、描画されるテキストに伸縮度が適用されます。

QTextEdit のようなリッチテキストを扱うウィジェットでは、QFont を直接設定するのではなく、QTextCharFormat を通じてフォント属性を設定します。

#include <QApplication>
#include <QTextEdit>
#include <QFont>
#include <QTextCharFormat>
#include <QTextCursor>

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

    QTextEdit textEdit;
    textEdit.setWindowTitle("QTextEdit with QFont::setStretch()");

    QTextCursor cursor = textEdit.textCursor();
    QTextCharFormat format;
    QFont font;
    font.setFamily("Meiryo UI"); // 例として日本語フォントを指定
    font.setPointSize(16);

    // 標準のテキスト
    format.setFont(font);
    format.setFontStretch(QFont::Unstretched);
    cursor.insertText("これは標準のフォントです。\n", format);

    // 拡張されたテキスト
    format.setFontStretch(QFont::ExtraExpanded); // 150% に拡張
    cursor.insertText("これは拡張されたフォントです。\n", format);

    // 圧縮されたテキスト
    format.setFontStretch(QFont::UltraCondensed); // 50% に圧縮
    cursor.insertText("これは圧縮されたフォントです。\n", format);

    // 数値で直接指定
    format.setFontStretch(180); // 180% に拡張
    cursor.insertText("これは数値で指定したフォントです。\n", format);

    textEdit.show();

    return app.exec();
}

この例では、QTextCharFormatsetFontStretch() メソッドを使用しています。QTextEdit のカーソル(QTextCursor)を操作して、特定のテキストブロックにフォントの伸縮度を含むフォーマットを適用しています。



QPainter::scale() を使用する (描画時のスケーリング)

これはフォント自体を伸縮させるのではなく、描画コンテキスト全体をスケーリングする方法です。テキストだけでなく、その後に描画されるすべての要素にも影響を与えます。

  • 使用例:

    #include <QApplication>
    #include <QWidget>
    #include <QPainter>
    #include <QFont>
    
    class ScaledTextWidget : public QWidget {
    public:
        ScaledTextWidget(QWidget *parent = nullptr) : QWidget(parent) {
            setWindowTitle("QPainter::scale() Example");
            setFixedSize(400, 300);
        }
    
    protected:
        void paintEvent(QPaintEvent *event) override {
            Q_UNUSED(event);
            QPainter painter(this);
            painter.setRenderHint(QPainter::Antialiasing);
    
            QFont font("Arial", 24);
            painter.setFont(font);
    
            // 標準のテキスト
            painter.drawText(20, 50, "Standard Text");
    
            // 1.5倍に横方向にスケーリング
            painter.save(); // 現在の描画状態を保存
            painter.translate(20, 100); // 描画開始位置を調整
            painter.scale(1.5, 1.0); // 横方向のみ1.5倍にスケーリング
            painter.drawText(0, 0, "Scaled Text (1.5x width)");
            painter.restore(); // 保存した描画状態に戻す
    
            // 0.7倍に横方向にスケーリング
            painter.save();
            painter.translate(20, 150);
            painter.scale(0.7, 1.0); // 横方向のみ0.7倍にスケーリング
            painter.drawText(0, 0, "Scaled Text (0.7x width)");
            painter.restore();
        }
    };
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
        ScaledTextWidget widget;
        widget.show();
        return app.exec();
    }
    
  • 欠点:

    • ピクセルパーフェクトな描画が難しくなる場合がある。
    • スケーリングがテキストだけでなく、その後の描画全体に影響を与えるため、注意が必要。必要に応じてQPainter::save()restore()を使用する。
    • テキストのレンダリング品質が低下する可能性がある。特に小さいフォントで顕著。
  • 利点:

    • QFont::setStretch() がサポートされていないフォントや、期待通りの効果が得られない場合に有効。
    • 任意の浮動小数点数で柔軟にスケーリングできる。
    • 非常に動的なスケーリングが必要な場合に適している(例: アニメーション)。

QFontDatabase を使用して既存の伸縮フォントを検索する

一部のフォントファミリー(例: Arial Narrow, Impactなど)には、すでに「Condensed」や「Extended」といったスタイルのフォントが別個のフォントファイルとして存在します。QFontDatabase を使って、システムにインストールされているこれらのフォントを検索し、直接使用することができます。

  • 使用例:

    #include <QApplication>
    #include <QLabel>
    #include <QFont>
    #include <QFontDatabase>
    #include <QVBoxLayout>
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
    
        QWidget window;
        QVBoxLayout *layout = new QVBoxLayout(&window);
    
        QLabel *label1 = new QLabel("Normal Arial");
        QFont font1("Arial", 20);
        label1->setFont(font1);
        layout->addWidget(label1);
    
        // Arial Narrow がインストールされているか確認し、使用
        // Windowsでは通常インストールされている
        if (QFontDatabase::has</p>
    </td>
    <td>
    <p dir="auto">Family("Arial Narrow")) {
            QLabel *label2 = new QLabel("Arial Narrow (Condensed)");
            QFont font2("Arial Narrow", 20); // 特定のフォントファミリーを指定
            label2->setFont(font2);
            layout->addWidget(label2);
        } else {
            QLabel *label2 = new QLabel("Arial Narrow not found.");
            layout->addWidget(label2);
        }
    
        // Impact のような元々幅広なフォント
        if (QFontDatabase::hasFamily("Impact")) {
            QLabel *label3 = new QLabel("Impact Font (Naturally Wide)");
            QFont font3("Impact", 20);
            label3->setFont(font3);
            layout->addWidget(label3);
        } else {
            QLabel *label3 = new QLabel("Impact not found.");
            layout->addWidget(label3);
        }
    
        window.setWindowTitle("QFontDatabase Stretch Example");
        window.show();
    
        return app.exec();
    }
    

    QFontDatabase::hasFamily() で特定のフォントが存在するかを確認し、存在すればそのフォントを直接使用しています。

  • 欠点:

    • 必要な伸縮スタイルのフォントがシステムにインストールされている必要がある。
    • 任意の伸縮率を適用することはできない(インストールされているスタイルのみ)。
  • 利点:

    • フォントデザイナーが意図した通りの見た目になる。
    • レンダリング品質が高い。
    • QFont::setStretch()でうまくいかない場合に確実な方法。

プロポーショナルフォントや固定幅フォントの選択

これは直接的な「伸縮」ではありませんが、テキストの横幅を制御する別の方法です。

  • 使用例:

    #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);
    
        QLabel *label1 = new QLabel("This is a proportional font (Arial).");
        QFont font1("Arial", 16);
        label1->setFont(font1);
        layout->addWidget(label1);
    
        QLabel *label2 = new QLabel("This is a monospace font (Courier New).");
        QFont font2("Courier New", 16);
        label2->setFont(font2);
        layout->addWidget(label2);
    
        window.setWindowTitle("Proportional vs Monospace");
        window.show();
    
        return app.exec();
    }
    
  • 欠点:

    • 柔軟な伸縮はできない。
  • 利点:

    • フォントの設計に忠実な表示。
    • 特別なスケーリング処理が不要。
  • 固定幅フォント (Monospace Font): すべての文字の幅が同じフォント(例: Courier New, Consolas)。コードエディタやアラインメントが重要なテキストに適しています。

  • プロポーショナルフォント: 文字ごとに幅が異なるフォント(例: Arial, Times New Roman)。標準的なテキスト表示に適しています。

  • 単に文字の幅を揃えたい場合は、固定幅フォントの選択を検討します。
  • 特定の「Condensed」や「Expanded」スタイルが明確に定義されているフォントを使用したい場合は、QFontDatabase を介して直接そのフォントをロードするのが最善です。
  • QFont::setStretch() で望む結果が得られない、または非常に柔軟な伸縮(小数点以下のスケーリングなど)が必要な場合は、QPainter::scale() を検討します。ただし、描画品質に注意が必要です。
  • フォントデザイナーが意図した伸縮を優先し、かつわずかな伸縮で十分な場合は、まず QFont::setStretch() を試します。