addSimpleText を使いこなす!Qt グラフィックスプログラミングの基礎【日本語チュートリアル】

2025-04-26

QGraphicsScene::addSimpleText() とは

QGraphicsScene::addSimpleText() は、Qtのグラフィックスビューフレームワークにおいて、シーン上にシンプルなテキストアイテムを追加するための便利な関数です。この関数を使うと、QFont で指定したフォントを持つ QGraphicsSimpleTextItem オブジェクトが作成され、シーンに追加されます。

機能と特徴

  • 変形
    スケールや回転などの変形も適用可能です。
  • 位置調整
    作成された QGraphicsSimpleTextItem オブジェクトに対して、setPos() などの関数を使ってシーン内の位置を調整できます。
  • フォント設定
    表示するテキストのフォントは、引数として渡す QFont オブジェクトで制御できます。
  • 軽量
    QGraphicsTextItem よりもリソース消費が少なく、パフォーマンスが求められる場面で有効です。
  • シンプルなテキスト表示
    リッチテキストのような複雑な書式設定はできませんが、基本的なテキストを効率的に表示するのに適しています。

関数のシグネチャ

QGraphicsSimpleTextItem *addSimpleText(const QString &text, const QFont &font = QFont());
  • font (const QFont & = QFont())
    テキストの描画に使用するフォントです。デフォルトでは、システムのデフォルトフォントが使用されます。
  • text (const QString &)
    シーンに追加するテキスト文字列です。

使用例

以下は、QGraphicsScene::addSimpleText() を使ってシーンにテキストを追加する簡単な例です。

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

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

    // グラフィックスシーンを作成
    QGraphicsScene scene;

    // 表示するテキストとフォントを作成
    QString myText = "こんにちは、Qt!";
    QFont myFont("Arial", 24);

    // シーンにシンプルなテキストアイテムを追加
    QGraphicsSimpleTextItem *textItem = scene.addSimpleText(myText, myFont);

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

    // グラフィックスビューを作成し、シーンを設定
    QGraphicsView view(&scene);
    view->show();

    return a.exec();
}

この例では、"こんにちは、Qt!" というテキストを Arial フォントのサイズ 24 でシーンの (50, 50) の位置に追加し、それをグラフィックスビューに表示しています。

QGraphicsTextItem との比較

より複雑なテキストの書式設定(色、スタイル、アンカーなど)が必要な場合は、QGraphicsScene::addText() を使用して作成される QGraphicsTextItem の方が適しています。一方、シンプルなテキスト表示でパフォーマンスを重視する場合は、QGraphicsScene::addSimpleText() がより良い選択肢となります。



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

QGraphicsScene::addSimpleText() 自体は比較的単純な関数ですが、その使用方法や関連する要素によっていくつかの一般的なエラーや予期しない動作が発生することがあります。以下に主なケースと対処法を挙げます。

テキストが表示されない

  • トラブルシューティング

    • QGraphicsView が作成され、setScene()QGraphicsScene が設定されているか確認してください。
    • テキストアイテムの pos() を確認し、ビューの範囲内に移動してみてください。ビューのサイズや原点も考慮してください。
    • アイテムの Z値を調整してみてください (setZValue())。
    • 適切なフォントサイズを設定しているか確認してください。
    • テキストの色 (QGraphicsSimpleTextItem::setBrush()) と背景色を確認してください。
    • シーンにビューが関連付けられていない
      QGraphicsScene に追加したアイテムは、QGraphicsView に設定して表示する必要があります。ビューが設定されていない場合、シーンの内容は見えません。
    • アイテムの位置がビューの範囲外
      setPos() などで設定したテキストアイテムの位置が、ビューの表示範囲外にある可能性があります。
    • アイテムが他のアイテムに隠れている
      Z値(描画順序)が低いアイテムの上に、不透明な他のアイテムが重なっている可能性があります。
    • フォントサイズが極端に小さい
      フォントサイズが小さすぎて、実質的に見えない場合があります。
    • テキストの色と背景色が同じ
      テキストの色とビューまたはシーンの背景色が同じ場合、テキストが見えません。デフォルトのテキスト色は黒です。

フォントが意図した通りに表示されない

  • トラブルシューティング

    • QFontDatabase::families() などを使って、システムにインストールされているフォントを確認し、存在するフォントを指定してみてください。
    • QFont オブジェクトのプロパティ(ファミリー、ポイントサイズ、スタイルなど)が意図した通りに設定されているか確認してください。
    • デフォルトフォントで表示されるか試してみてください(QFont() を引数に渡さない)。
  • 原因

    • 指定したフォントがシステムにインストールされていない
      QFont で指定したフォントがシステムに存在しない場合、代替フォントで表示されることがあります。
    • フォントの設定ミス
      フォントファミリー、サイズ、スタイル(太字、斜体など)の設定が意図した通りになっていない可能性があります。

テキストのアンチエイリアスが効いていない(ギザギザに見える)

  • トラブルシューティング

    • QGraphicsView または QGraphicsScene に対して、アンチエイリアスのレンダリングヒントを設定してください。
    view->setRenderHint(QPainter::Antialiasing);
    // または
    scene->setRenderHint(QPainter::Antialiasing);
    
  • 原因

    • ビューまたはシーンのレンダリングヒントが設定されていない
      アンチエイリアスを有効にするためのレンダリングヒントが設定されていない可能性があります。

テキストのパフォーマンスの問題(多数のテキストアイテムがある場合など)

  • トラブルシューティング

    • もしテキストの内容が頻繁に変わらないのであれば、画像を生成して表示するなどの別の方法を検討してください。
    • 複雑なテキスト表現が必要な場合は、QGraphicsTextItem の使用も検討してください(ただし、こちらはよりリソースを消費する可能性があります)。
    • 必要のないテキストアイテムは適切に削除してください。
  • 原因

    • 多数の QGraphicsSimpleTextItem を使用している
      QGraphicsSimpleTextItem は軽量ですが、大量に作成すると描画処理に負荷がかかることがあります。
  • トラブルシューティング

    • 親アイテムとの関係を確認し、必要であれば親を設定しないか、適切な親子関係になるように調整してください。
    • シーンの座標系とアイテムのローカル座標系を意識して、位置設定を行ってください。
  • 原因

    • 親アイテムとの関係
      テキストアイテムが他のアイテムの子になっている場合、親アイテムの変形(移動、回転、スケール)の影響を受けます。意図しない位置やサイズになることがあります。
    • シーンの座標系
      シーンの座標系を理解し、アイテムのポジショニングが適切に行われているか確認してください。

デバッグのヒント

  • 簡単なテストケース
    問題が発生している箇所を切り出した簡単なテストケースを作成し、原因を特定しやすくしてください。
  • ログ出力
    テキストの内容、位置、フォントなどの情報をログに出力して、意図した値になっているか確認してください。
  • 境界線の描画
    アイテムの境界線を表示するデバッグオプションを利用して、アイテムの実際のサイズや位置を確認するのも有効です。


基本的な例:シンプルなテキストの追加

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

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

    // グラフィックスシーンを作成
    QGraphicsScene scene;

    // 表示するテキスト
    QString text = "Hello, Simple Text!";

    // デフォルトフォントでテキストを追加
    QGraphicsSimpleTextItem *item1 = scene.addSimpleText(text);
    item1->setPos(10, 10); // 位置を設定

    // フォントを指定してテキストを追加
    QFont font("Arial", 16);
    QGraphicsSimpleTextItem *item2 = scene.addSimpleText("Another Text", font);
    item2->setPos(10, 50);

    // グラフィックスビューを作成し、シーンを表示
    QGraphicsView view(&scene);
    view->show();

    return a.exec();
}

この例では、2つのシンプルなテキストアイテムをシーンに追加しています。

  • 2つ目は "Arial" フォントのサイズ 16 を指定しています。 それぞれのテキストアイテムに対して setPos() を呼び出し、シーン内での位置を設定しています。最後に、QGraphicsView にシーンを設定して表示しています。
  • 1つ目はデフォルトのフォントを使用しています。

例2:テキストの色と位置の調整

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QFont>
#include <QBrush>
#include <QColor>

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

    QGraphicsScene scene;

    QFont font("Times New Roman", 20, QFont::Bold);
    QString colorfulText = "Colorful Text";
    QGraphicsSimpleTextItem *textItem = scene.addSimpleText(colorfulText, font);

    // テキストの色を設定 (ブラシを使用)
    QBrush redBrush(Qt::red);
    textItem->setBrush(redBrush);

    // 中央に配置するための計算
    QRectF textRect = textItem->boundingRect();
    QRectF sceneRect(0, 0, 300, 200);
    textItem->setPos(sceneRect.center() - textRect.center());

    // シーンの境界を設定 (ビューのスクロールを防ぐ)
    scene.setSceneRect(sceneRect);

    QGraphicsView view(&scene);
    view->show();

    return a.exec();
}

この例では、テキストの色を赤色に設定しています。QGraphicsSimpleTextItem::setBrush() 関数に QBrush オブジェクトを渡すことでテキストの色を変更できます。また、boundingRect() でテキストの矩形を取得し、シーンの中央に配置する計算を行っています。setSceneRect() はシーンの境界を設定し、ビューが不必要にスクロールするのを防ぎます。

例3:マウスイベントへの応答(簡単なインタラクション)

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsSimpleTextItem>
#include <QFont>
#include <QGraphicsItem>
#include <QMouseEvent>

class ClickableTextItem : public QGraphicsSimpleTextItem
{
public:
    ClickableTextItem(const QString &text, const QFont &font, QGraphicsItem *parent = nullptr)
        : QGraphicsSimpleTextItem(text, font, parent)
    {
        setAcceptHoverEvents(true); // ホバーイベントを有効にする
    }

protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override
    {
        if (event->button() == Qt::LeftButton) {
            qDebug() << "Text clicked: " << text();
            // クリック時の処理をここに記述
        }
        QGraphicsSimpleTextItem::mousePressEvent(event);
    }

    void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override
    {
        // マウスカーソルがアイテムに入った時の処理
        setBrush(QBrush(Qt::blue));
        QGraphicsSimpleTextItem::hoverEnterEvent(event);
    }

    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override
    {
        // マウスカーソルがアイテムから離れた時の処理
        setBrush(QBrush(Qt::black));
        QGraphicsSimpleTextItem::hoverLeaveEvent(event);
    }
};

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

    QGraphicsScene scene;

    QFont font("Verdana", 18);
    ClickableTextItem *clickableText = new ClickableTextItem("Click Me!", font);
    clickableText->setPos(50, 50);
    clickableText->setFlag(QGraphicsItem::ItemIsSelectable); // 選択可能にする (必要に応じて)
    scene.addItem(clickableText);

    QGraphicsView view(&scene);
    view->show();

    return a.exec();
}

この例では、QGraphicsSimpleTextItem を継承した ClickableTextItem クラスを作成し、マウスのクリックイベントとホバーイベントに応答するようにしています。

  • setFlag(QGraphicsItem::ItemIsSelectable) を呼び出すと、アイテムを選択できるようになります(必要に応じて)。
  • setAcceptHoverEvents(true) を呼び出すことで、ホバーイベントを有効にしています。
  • hoverEnterEvent()hoverLeaveEvent() をオーバーライドして、マウスカーソルがアイテムの上にあるときにテキストの色を青色に、離れたときに黒色に戻すようにしています。
  • mousePressEvent() をオーバーライドして、左クリックされたときにメッセージをコンソールに出力するようにしています。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QFont>
#include <QGraphicsItemGroup>

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

    QGraphicsScene scene;

    QFont font("Courier New", 14);

    // 複数のテキストアイテムを作成
    QGraphicsSimpleTextItem *text1 = new QGraphicsSimpleTextItem("Text A", font);
    text1->setPos(0, 0);
    QGraphicsSimpleTextItem *text2 = new QGraphicsSimpleTextItem("Text B", font);
    text2->setPos(20, 20);
    QGraphicsSimpleTextItem *text3 = new QGraphicsSimpleTextItem("Text C", font);
    text3->setPos(40, 0);

    // アイテムグループを作成し、テキストアイテムを追加
    QGraphicsItemGroup *textGroup = new QGraphicsItemGroup();
    textGroup->addToGroup(text1);
    textGroup->addToGroup(text2);
    textGroup->addToGroup(text3);
    textGroup->setPos(50, 50); // グループ全体の位置を設定
    scene.addItem(textGroup);

    QGraphicsView view(&scene);
    view->show();

    return a.exec();
}


QGraphicsScene::addText() と QGraphicsTextItem の利用

  • 使用例
  • 用途
    複雑なテキスト表現、装飾されたテキスト、ドキュメントのようなテキスト表示が必要な場合。
  • 特徴
    リッチテキストのサポート、より細やかな書式設定が可能(色、フォントのスタイル、アンカー、テキストのレイアウトなど)。HTML形式のテキストも表示できます。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QFont>
#include <QTextDocument>

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

    QGraphicsScene scene;

    // 基本的なテキストの追加(QFont を使用)
    QFont font("Serif", 18);
    QGraphicsTextItem *textItem1 = scene.addText("Basic Text with Font", font);
    textItem1->setPos(10, 10);

    // リッチテキストの追加(HTML形式)
    QGraphicsTextItem *textItem2 = scene.addText("<h1>Rich <u>Text</u></h1><p><font color='blue'>With</font> HTML</p>");
    textItem2->setPos(10, 50);

    // QTextDocument を使用した高度な書式設定
    QTextDocument *doc = new QTextDocument();
    doc->setHtml("<font size='+2' face='Arial' color='green'>Styled Text</font><br>With multiple lines.");
    QGraphicsTextItem *textItem3 = new QGraphicsTextItem(doc);
    textItem3->setPos(10, 150);
    scene.addItem(textItem3); // addText() を使わずに addItem() で追加

    QGraphicsView view(&scene);
    view->setSceneRect(scene.itemsBoundingRect()); // シーンの境界をアイテムに合わせて設定
    view->show();

    return a.exec();
}

addText()QGraphicsTextItem オブジェクトを作成してシーンに追加します。コンストラクタにプレーンテキストと QFont を渡す基本的な使い方の他に、HTML形式の文字列を渡すことでリッチテキストを表示できます。また、QTextDocument を作成してより複雑な書式設定を行い、それを QGraphicsTextItem に設定することも可能です。この場合、scene->addItem() を使ってアイテムをシーンに追加します。

QPainter を直接使用した描画

  • 使用例
  • 用途
    特殊なテキスト表現、他のグラフィックス要素と統合されたテキスト描画が必要な場合。
  • 特徴
    グラフィックスアイテムの paint() 関数内で QPainter を使用して、カスタムなテキスト描画を行うことができます。これにより、テキストの回転、スケーリング、グラデーション、影などの高度な効果を適用できます。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QPainter>
#include <QFont>

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

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

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

        // 追加の描画処理(例:背景の円)
        painter->setBrush(Qt::yellow);
        painter->drawEllipse(boundingRect().adjusted(-5, -5, 5, 5));
    }

private:
    QString m_text;
    QFont m_font;
};

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

    QGraphicsScene scene;

    QFont font("Cursive", 24);
    CustomTextItem *customText = new CustomTextItem("Custom Painted Text", font);
    customText->setPos(50, 50);
    scene.addItem(customText);

    QGraphicsView view(&scene);
    view->setSceneRect(scene.itemsBoundingRect());
    view->show();

    return a.exec();
}

この例では、QGraphicsItem を継承した CustomTextItem クラスを作成し、paint() 関数内で QPainter を使用してテキストを描画しています。boundingRect() 関数はアイテムの境界矩形を定義する必要があります。paint() 関数内では、フォントやペンの色を設定し、drawText() 関数でテキストを描画しています。さらに、背景に円を描画するなどのカスタムな描画も可能です。

QLabel を QGraphicsProxyWidget として利用

  • 使用例
  • 用途
    既存のウィジェットの機能をグラフィックスシーンに統合したい場合。
  • 特徴
    Qtの標準ウィジェットである QLabel をグラフィックスシーンに埋め込むことができます。これにより、QLabel の豊富な機能(リッチテキスト表示、画像表示など)をシーン内で利用できます。
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QLabel>
#include <QGraphicsProxyWidget>
#include <QFont>

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

    QGraphicsScene scene;

    QLabel *label = new QLabel("<b>QLabel in Scene</b><br><font color='red'>Supports HTML</font>");
    QFont font("Sans Serif", 16);
    label->setFont(font);

    QGraphicsProxyWidget *proxy = scene.addWidget(label);
    proxy->setPos(20, 20);

    QGraphicsView view(&scene);
    view->setSceneRect(scene.itemsBoundingRect());
    view->show();

    return a.exec();
}

この例では、QLabel を作成し、scene->addWidget() を使用して QGraphicsProxyWidget にラップしてシーンに追加しています。QLabel はリッチテキストやスタイルシートによる装飾もサポートしているため、比較的柔軟なテキスト表示が可能です。

テキストレンダリングエンジンとの統合(高度なケース)

  • 用途
    特殊なテキスト表現、高度なタイポグラフィ制御、パフォーマンス最適化などが求められる場合(通常は高度な知識が必要です)。
  • 特徴
    FreeTypeなどの外部テキストレンダリングライブラリをQtアプリケーションに統合し、より高度なテキストレイアウトやフォント制御を行うことができます。

QGraphicsScene::addSimpleText() は手軽にシンプルなテキストを表示するのに適していますが、より複雑な要求には以下の代替方法があります。

  • 外部テキストレンダリングエンジンの統合
    高度なテキスト制御や最適化が必要な場合(上級者向け)。
  • QLabel を QGraphicsProxyWidget として利用
    既存の QLabel の機能をシーン内で利用したい場合。
  • QPainter を直接使用した描画
    カスタムなテキスト効果や他のグラフィックス要素との統合が必要な場合。
  • QGraphicsScene::addText() と QGraphicsTextItem
    リッチテキストや詳細な書式設定が必要な場合。