【Qt】QGraphicsSceneのフォントを使いこなす!初心者向け徹底ガイド

2025-05-27

役割

  • デフォルトフォントの設定
    scene()->setFont(const QFont &font) のように呼び出すことで、そのシーンのデフォルトフォントを指定された QFont オブジェクトに設定できます。
  • デフォルトフォントの取得
    scene()->font() のように呼び出すことで、そのシーンに現在設定されているデフォルトのフォントオブジェクト (QFont) を取得できます。

詳細

QGraphicsScene は、グラフィカルアイテムを管理し、それらのインタラクションを処理するキャンバスのようなものです。シーンに追加されるテキストアイテム (QGraphicsTextItem) などは、特にフォントが明示的に設定されていない場合、このシーンのデフォルトフォントを使用します。

  1. デフォルトフォントの取得と情報の表示

    #include <QApplication>
    #include <QGraphicsScene>
    #include <QDebug>
    #include <QFont>
    
    int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
        QGraphicsScene scene;
    
        QFont defaultFont = scene.font();
        qDebug() << "デフォルトフォントのファミリ:" << defaultFont.family();
        qDebug() << "デフォルトフォントのポイントサイズ:" << defaultFont.pointSize();
    
        return a.exec();
    }
    

    この例では、最初にシーンのデフォルトフォントを取得し、そのフォントのファミリ名とポイントサイズをコンソールに出力しています。

  2. デフォルトフォントの設定

    #include <QApplication>
    #include <QGraphicsScene>
    #include <QGraphicsView>
    #include <QGraphicsTextItem>
    #include <QFont>
    
    int main(int argc, char *argv[]) {
        QApplication a(argc, argv);
        QGraphicsScene scene;
        QGraphicsView view(&scene);
    
        // 新しいフォントを作成
        QFont newFont("Arial", 16);
        newFont.setBold(true);
    
        // シーンのデフォルトフォントを設定
        scene.setFont(newFont);
    
        // テキストアイテムを作成 (デフォルトフォントを使用)
        QGraphicsTextItem *textItem = scene.addText("Hello, Qt Graphics!");
    
        view.show();
        return a.exec();
    }
    

    この例では、まず "Arial" フォント、サイズ 16、ボールド属性を持つ新しい QFont オブジェクトを作成しています。次に、scene.setFont(newFont) を呼び出すことで、このフォントをシーンのデフォルトフォントとして設定しています。その後に追加された QGraphicsTextItem は、特にフォントを指定しない限り、この新しいデフォルトフォントで描画されます。

  • シーンのデフォルトフォントを設定することで、シーンに追加する新しいテキストアイテムの基本的な外観を統一することができます。
  • 個々のグラフィカルアイテム(例えば QGraphicsTextItem)は、自身のフォントを個別に設定することができます。その場合、アイテム固有のフォント設定がシーンのデフォルトフォントよりも優先されます。


一般的なエラーとトラブルシューティング

    • 原因
      • テキストアイテム (QGraphicsTextItem) が、setFont() メソッドなどで明示的に別のフォントを設定されている。アイテム固有のフォント設定は、シーンのデフォルトフォントよりも優先されます。
      • フォントオブジェクト (QFont) の設定が意図通りになっていない(フォントファミリ名、サイズ、スタイルなどが間違っている)。
      • フォントファイルがシステムにインストールされていないため、指定したフォントが見つからない。
    • トラブルシューティング
      • 問題のテキストアイテムのフォント設定を確認してください。textItem->font() で現在のフォントを取得し、意図した設定になっているか調べます。
      • QFont オブジェクトの生成時に指定したフォント名が正しいか、スペルミスがないか確認してください。
      • 必要なフォントがシステムにインストールされているか確認してください。QFontDatabase クラスを使用して、利用可能なフォントファミリを確認できます。
      • フォントのスタイル(ボールド、イタリックなど)が正しく設定されているか確認してください。
  1. シーンのデフォルトフォントを設定しても、既存のテキストアイテムの表示が変わらない

    • 原因

      • scene->setFont() を呼び出す前に、すでにテキストアイテムがシーンに追加されている場合、それらのアイテムは作成時点のデフォルトフォント(または個別に設定されたフォント)を保持しています。シーンのデフォルトフォントを変更しても、既存のアイテムのフォントは自動的には更新されません。
    • トラブルシューティング

      • シーンのデフォルトフォントを設定した後でテキストアイテムを追加するようにしてください。
      • 既存のテキストアイテムのフォントを新しいデフォルトフォントに合わせて明示的に設定する必要があります。シーン内のすべての QGraphicsTextItem を取得し、それぞれの setFont() を呼び出すことで更新できます。
      QFont newDefaultFont("NewFont", 12);
      scene->setFont(newDefaultFont);
      
      foreach (QGraphicsItem *item, scene->items()) {
          if (QGraphicsTextItem *textItem = qgraphicsitem_cast<QGraphicsTextItem*>(item)) {
              textItem->setFont(newDefaultFont);
          }
      }
      
  2. パフォーマンスの問題(多数のテキストアイテムで異なるフォントを使用する場合)

    • 原因
      • シーン内に多数のテキストアイテムがあり、それぞれが異なるフォントを使用している場合、フォントのキャッシュやレンダリング処理に負荷がかかり、パフォーマンスが低下する可能性があります。
    • トラブルシューティング
      • できる限りシーン全体で共通のフォントを使用するように設計を見直してください。
      • フォントの変更を頻繁に行わないようにしてください。
      • 必要に応じて、テキストアイテムをラスタライズするなど、パフォーマンス改善のための他の手法を検討してください。

QGraphicsScene::font 自体のエラーは少ないですが、フォントの設定や適用、そしてフォントのレンダリングに関連する問題は起こりえます。問題解決のためには、以下の点に着目して調査を進めることが重要です。

  • 文字セットのサポート
    使用するフォントが表示したい文字をサポートしているか。
  • フォントの可用性
    指定したフォントがシステムにインストールされているか。
  • フォントの適用範囲
    シーンのデフォルトフォントなのか、個々のアイテムのフォントなのか。
  • フォントオブジェクト (QFont) の設定内容
    ファミリ名、サイズ、スタイルなどが正しいか。


#include <QApplication>
#include <QGraphicsScene>
#include <QDebug>
#include <QFont>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    QGraphicsScene scene;

    // シーンのデフォルトフォントを取得
    QFont defaultFont = scene.font();

    // フォントの情報を表示
    qDebug() << "デフォルトフォントのファミリ:" << defaultFont.family();
    qDebug() << "デフォルトフォントのポイントサイズ:" << defaultFont.pointSize();

    return a.exec();
}

解説

  1. #include <QApplication>, #include <QGraphicsScene>, #include <QDebug>, #include <QFont>: 必要なヘッダーファイルをインクルードします。
  2. QApplication a(argc, argv);: Qt アプリケーションのインスタンスを作成します。
  3. QGraphicsScene scene;: QGraphicsScene のインスタンスを作成します。
  4. QFont defaultFont = scene.font();: scene.font() を呼び出して、シーンの現在のデフォルトフォントを取得し、QFont オブジェクト defaultFont に格納します。
  5. qDebug() << "デフォルトフォントのファミリ:" << defaultFont.family();: 取得したフォントオブジェクトの family() メソッドを呼び出し、フォントファミリ名(例: "Helvetica")をコンソールに出力します。
  6. qDebug() << "デフォルトフォントのポイントサイズ:" << defaultFont.pointSize();: 取得したフォントオブジェクトの pointSize() メソッドを呼び出し、フォントのポイントサイズ(例: 12)をコンソールに出力します。

この例では、新しい QFont オブジェクトを作成し、それをシーンのデフォルトフォントとして設定します。その後、シーンに追加した QGraphicsTextItem が、この新しいデフォルトフォントを使用していることを確認します。

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsTextItem>
#include <QFont>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    QGraphicsScene scene;
    QGraphicsView view(&scene);

    // 新しいフォントを作成 (Arial, サイズ 20, ボールド)
    QFont newFont("Arial", 20, QFont::Bold);

    // シーンのデフォルトフォントを設定
    scene.setFont(newFont);

    // テキストアイテムを作成 (フォントは明示的に設定しない)
    QGraphicsTextItem *textItem = scene.addText("デフォルトフォントで表示");

    // テキストアイテムの位置を設定
    textItem->setPos(50, 50);

    view.show();
    return a.exec();
}

解説

  1. 必要なヘッダーファイルをインクルードします。
  2. QApplicationQGraphicsScene、そしてシーンを表示するための QGraphicsView のインスタンスを作成します。
  3. QFont newFont("Arial", 20, QFont::Bold);: "Arial" フォント、サイズ 20、ボールド属性を持つ新しい QFont オブジェクトを作成します。
  4. scene.setFont(newFont);: 作成した newFontscene.setFont() を使用してシーンのデフォルトフォントとして設定します。
  5. QGraphicsTextItem *textItem = scene.addText("デフォルトフォントで表示");: scene.addText() を使用してテキストアイテムを作成します。ここではフォントを明示的に指定していないため、シーンのデフォルトフォントが適用されます。
  6. textItem->setPos(50, 50);: テキストアイテムの位置を設定します。
  7. view.show();: シーンを表示するビューを表示します。

この例では、最初にいくつかのテキストアイテムをシーンに追加し、それぞれ異なるフォントを設定します。その後、シーンのデフォルトフォントを変更し、シーン内のすべての QGraphicsTextItem のフォントを新しいデフォルトフォントに更新します。

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsTextItem>
#include <QFont>
#include <QDebug>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    QGraphicsScene scene;
    QGraphicsView view(&scene);

    // 異なるフォントでテキストアイテムを作成
    QFont font1("Times New Roman", 14);
    QGraphicsTextItem *item1 = scene.addText("Times New Roman", font1);
    item1->setPos(10, 10);

    QFont font2("Courier New", 16);
    QGraphicsTextItem *item2 = scene.addText("Courier New", font2);
    item2->setPos(10, 40);

    // 新しいデフォルトフォントを作成
    QFont newDefaultFont("Verdana", 18, QFont::Italic);
    scene.setFont(newDefaultFont);
    qDebug() << "デフォルトフォントを変更しました:" << newDefaultFont.family() << newDefaultFont.pointSize();

    // シーン内のすべてのテキストアイテムのフォントを更新
    foreach (QGraphicsItem *item, scene.items()) {
        if (QGraphicsTextItem *textItem = qgraphicsitem_cast<QGraphicsTextItem*>(item)) {
            textItem->setFont(newDefaultFont);
            qDebug() << "テキストアイテムのフォントを更新:" << textItem->toPlainText();
        }
    }

    view.show();
    return a.exec();
}
  1. 必要なヘッダーファイルをインクルードします。
  2. QApplicationQGraphicsSceneQGraphicsView のインスタンスを作成します。
  3. 異なるフォント (font1font2) を使用して、2つの QGraphicsTextItem をシーンに追加し、位置を設定します。
  4. 新しいデフォルトフォント (newDefaultFont) を作成し、scene.setFont() でシーンのデフォルトフォントを設定します。
  5. scene.items() を使用してシーン内のすべてのアイテムを取得し、qgraphicsitem_cast<QGraphicsTextItem*>(item)QGraphicsTextItem 型のアイテムであるかを確認します。
  6. もしテキストアイテムであれば、その setFont() メソッドを新しいデフォルトフォントで呼び出し、フォントを更新します。


個々の QGraphicsTextItem に直接フォントを設定する

最も一般的で柔軟な方法は、シーンのデフォルトフォントに頼らず、個々の QGraphicsTextItem オブジェクトに対して setFont() メソッドを使用してフォントを設定する方法です。これにより、シーン内のテキストアイテムごとに異なるフォント、サイズ、スタイルなどを設定できます。

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsTextItem>
#include <QFont>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    QGraphicsScene scene;
    QGraphicsView view(&scene);

    // 1つ目のテキストアイテム
    QFont font1("Arial", 12);
    QGraphicsTextItem *textItem1 = scene.addText("Arial 12", font1);
    textItem1->setPos(10, 10);

    // 2つ目のテキストアイテム (異なるフォント)
    QFont font2("Times New Roman", 16, QFont::Bold);
    QGraphicsTextItem *textItem2 = scene.addText("Times New Roman 16 Bold", font2);
    textItem2->setPos(10, 40);

    view.show();
    return a.exec();
}

利点

  • 直感的
    特定のテキストの外観を直接制御できます。
  • 高い柔軟性
    各テキストアイテムに完全に独立したフォント設定が可能です。

欠点

  • 一貫性の維持
    シーン全体で特定のフォントスタイルを維持したい場合、すべてのアイテムに同じ設定を行う必要があります。
  • 冗長性
    多数のテキストアイテムがある場合、個別にフォントを設定する手間がかかります。

カスタムの QGraphicsItem サブクラスを作成し、その中でフォントを管理する

複数のテキスト要素を持つような複雑なカスタムアイテムを作成する場合、そのアイテムの描画処理 (paint() メソッド) の中で使用するフォントを管理する方法があります。

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QPainter>
#include <QFont>
#include <QRectF>

class MyCustomTextItem : public QGraphicsItem {
public:
    MyCustomTextItem(const QString &text, const QFont &font, QGraphicsItem *parent = nullptr)
        : QGraphicsItem(parent), m_text(text), m_font(font) {}

    QRectF boundingRect() const override {
        QFontMetricsF fm(m_font);
        return fm.boundingRect(m_text);
    }

protected:
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override {
        painter->setFont(m_font);
        painter->drawText(boundingRect(), Qt::AlignLeft | Qt::AlignTop, m_text);
    }

private:
    QString m_text;
    QFont m_font;
};

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    QGraphicsScene scene;
    QGraphicsView view(&scene);

    QFont customFont("Verdana", 14, QFont::Italic);
    MyCustomTextItem *customItem = new MyCustomTextItem("カスタムアイテムのテキスト", customFont);
    scene.addItem(customItem);

    view.show();
    return a.exec();
}

利点

  • 再利用性
    同じフォント設定を持つ複数のカスタムアイテムを簡単に作成できます。
  • カプセル化
    アイテムの描画に必要なフォント情報をアイテム内部で管理できます。

欠点

  • 複雑性
    単純なテキスト表示の場合、オーバーヘッドが大きくなる可能性があります。

スタイルシートを使用する (限定的)

Qt のスタイルシートは、QWidget ベースのウィジェットの外観をカスタマイズする強力なメカニズムですが、QGraphicsSceneQGraphicsItem に対して直接的にフォントスタイルを適用する機能は限定的です。ただし、QGraphicsProxyWidget を使用して QWidget をシーンに埋め込み、そのウィジェットにスタイルシートを適用することで、間接的にフォントを制御できます。

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsProxyWidget>
#include <QLabel>
#include <QFont>

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    QGraphicsScene scene;
    QGraphicsView view(&scene);

    QLabel *label = new QLabel("スタイルシート適用");
    label->setStyleSheet("font-family: 'Georgia'; font-size: 18px; font-style: italic;");

    QGraphicsProxyWidget *proxy = scene.addProxyWidget(label);
    proxy->setPos(50, 50);

    view.show();
    return a.exec();
}

利点

  • 分離
    デザインとロジックを分離できます。
  • 一貫性
    スタイルシートを使用すると、複数のウィジェットで一貫したスタイルを適用できます。

欠点

  • 柔軟性の制限
    QGraphicsTextItem のようなグラフィカルアイテムのすべてのフォントプロパティを完全に制御できるわけではありません。
  • 間接的
    QGraphicsItem に直接適用できるわけではありません。QGraphicsProxyWidget を介する必要があります。

外部設定ファイルやテーマシステムを利用する

アプリケーション全体でフォント設定を管理したい場合、設定ファイル (JSON、XML など) やテーマシステムを利用する方法があります。アプリケーションの起動時や設定変更時にこれらの設定を読み込み、必要に応じて QGraphicsTextItem やカスタムアイテムのフォントを更新します。

利点

  • カスタマイズ性
    ユーザーがフォント設定をカスタマイズできます。
  • 集中管理
    アプリケーション全体のフォント設定を一元的に管理できます。
  • 実装の複雑性
    設定ファイルの読み込みやテーマの適用ロジックを実装する必要があります。