Qt QGraphicsView::rotate() 完全ガイド:ビューの回転からトラブルシューティングまで

2025-05-27

QGraphicsView::rotate() とは

QGraphicsView::rotate(qreal angle)は、QtのGraphics View Frameworkにおいて、ビュー(表示領域)自体を回転させるための関数です。引数angleには、回転させたい角度を度数で指定します。

何が回転するのか?

この関数を呼び出すと、QGraphicsViewの表示内容全体が回転します。つまり、QGraphicsViewが担当している「シーン(QGraphicsScene)を見るための窓」が回転するイメージです。シーン内の個々のアイテム(QGraphicsItem)自体が回転するわけではありません。

なぜ使うのか?

  • ナビゲーション
    ユーザーがマウス操作などでビューを回転させられるようにする際に使われます。
  • ビューの視点変更
    特定の角度からシーンを見たい場合に利用します。例えば、CADアプリケーションで図面を傾けて表示したり、ゲームでカメラを回転させたりするような用途です。

注意点

  • 変換行列 (Transformation Matrix)
    QGraphicsView::rotate()は、内部的にQGraphicsViewの変換行列(QTransform)を変更することで回転を実現しています。複雑な複数の変換(拡大縮小、平行移動、回転)を組み合わせたい場合は、QGraphicsView::setTransform()QGraphicsView::transform()を使って直接QTransformオブジェクトを操作することもできます。
  • シーン内のアイテムの回転との違い
    QGraphicsItemにもsetRotation()という関数がありますが、これは個々のアイテムを回転させるものです。QGraphicsView::rotate()はビュー全体を回転させるため、混同しないように注意が必要です。例えば、ビューを90度回転させた場合、シーン内のすべてのアイテムがビュー上で90度傾いて表示されますが、各アイテム自体の内部的な座標や向きは変わりません。
  • 回転の中心
    デフォルトでは、ビューの中心を基準に回転します。もし異なる点を中心に回転させたい場合は、事前にQGraphicsView::setTransformOriginPoint()を使って回転の中心を設定する必要があります。

使用例

例えば、ボタンを押すとビューが90度回転するようにする場合、以下のようなコードになります。

// mainwindow.h
#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QPushButton>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);

private slots:
    void rotateView();

private:
    QGraphicsView *view;
    QGraphicsScene *scene;
    QPushButton *rotateButton;
};

// mainwindow.cpp
#include "mainwindow.h"
#include <QVBoxLayout>
#include <QGraphicsRectItem>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    scene = new QGraphicsScene(this);
    scene->addRect(0, 0, 100, 50, QPen(Qt::blue), QBrush(Qt::cyan)); // シーンに矩形を追加

    view = new QGraphicsView(scene, this);
    view->setRenderHint(QPainter::Antialiasing); // アンチエイリアシングを有効にする

    rotateButton = new QPushButton("Rotate View", this);
    connect(rotateButton, &QPushButton::clicked, this, &MainWindow::rotateView);

    QWidget *centralWidget = new QWidget(this);
    QVBoxLayout *layout = new QVBoxLayout(centralWidget);
    layout->addWidget(view);
    layout->addWidget(rotateButton);
    setCentralWidget(centralWidget);

    setWindowTitle("QGraphicsView Rotate Example");
    resize(400, 300);
}

void MainWindow::rotateView()
{
    // ビューを時計回りに45度回転させる
    view->rotate(45);
}

// main.cpp
#include <QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}


想定した回転が行われない、または全く回転しない

原因

  • レンダリングの問題
    特定のグラフィックスドライバーやQtのバージョンによっては、レンダリングの問題で回転が正しく表示されないことがあります。
  • 他の変換が干渉している
    以前に適用された他の変換(例: scale(), translate(), setTransform())が、現在の回転に影響を与えている可能性があります。
  • QGraphicsItem::setRotation()と混同している
    QGraphicsView::rotate()はビュー全体を回転させるもので、シーン内の個々のアイテムを回転させるものではありません。アイテムを回転させたい場合は、QGraphicsItem::setRotation()を使用する必要があります。
  • 変換の順序の問題
    複数の変換(移動、拡大縮小、回転)を適用する場合、その順序が重要です。QGraphicsViewの変換は内部的に変換行列(QTransform)を操作することで行われます。変換行列は非可換であるため、例えば「拡大してから回転」と「回転してから拡大」では結果が異なります。
  • 回転の中心が間違っている
    QGraphicsView::rotate()はデフォルトでビューの中心を基準に回転します。もし異なる点を中心に回転させたい場合、QGraphicsView::setTransformOriginPoint()で明示的に設定する必要があります。この設定を忘れると、期待通りの回転にならないことがあります。

トラブルシューティング

  • アンチエイリアシングの確認
    view->setRenderHint(QPainter::Antialiasing, true); を設定すると、回転後の表示が滑らかになることがあります。
  • 最小限のコードで再現する
    問題が複雑な場合は、QGraphicsViewと少数のアイテムだけを使った最小限のコードで問題が再現するかどうかを試します。これにより、問題の原因を特定しやすくなります。
  • resetTransform()を試す
    意図しない変換が残っている可能性がある場合、view->resetTransform(); を呼び出してビューの変換を初期状態に戻してから、改めて回転を適用してみてください。
  • デバッグ出力で変換行列を確認する
    QGraphicsView::transform()で現在の変換行列を取得し、その中身(m11, m12 など)をデバッグ出力して、意図した値になっているか確認します。
  • 変換の順序を見直す
    複数の変換を適用する場合は、目的の表示になるように変換の順序を試行錯誤してください。通常は、拡大縮小、回転、平行移動の順で適用することが多いですが、具体的なユースケースによって異なります。
  • setTransformOriginPoint()を確認する
    回転の中心が意図した通りになっているか確認してください。必要であれば、view->setTransformOriginPoint(QPointF(x, y)); のように設定します。

回転時に描画がちらつく、またはパフォーマンスが悪い

原因

  • レンダリングの最適化不足
    QGraphicsViewのレンダリングモードやキャッシュ設定が最適化されていない可能性があります。
  • 複雑なシーン
    シーン内に大量のアイテムがあったり、非常に複雑なアイテムがあったりすると、回転時の再描画に時間がかかります。
  • 再描画の頻度が高い
    アニメーションなどで連続的にrotate()を呼び出す場合、毎回の描画処理が重いためにちらつきやパフォーマンス低下が発生することがあります。

トラブルシューティング

  • アニメーションの最適化
    • QPropertyAnimationなどQtのアニメーションフレームワークを利用すると、より滑らかなアニメーションを実現できる場合があります。
    • 独自のアニメーションループを実装する場合は、QTimerなどを使用して適切なフレームレートを維持するようにしてください。
  • アイテムのキャッシュ
    シーン内の静的なアイテムが多い場合、QGraphicsItem::setCacheMode()を設定してアイテムの描画結果をキャッシュすることで、再描画の負荷を軽減できます。
  • レンダリングヒントの調整
    • view->setRenderHint(QPainter::Antialiasing, true);view->setRenderHint(QPainter::SmoothPixmapTransform, true); は描画品質を向上させますが、その分パフォーマンスに影響を与える可能性があります。試行錯誤して最適な設定を見つけましょう。
  • setViewportUpdateMode()の最適化
    • view->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); (デフォルト)は、変更された部分のみを更新しますが、複雑なシーンではそれでも重くなることがあります。
    • view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); は常に全体を再描画するため、逆にパフォーマンスが低下する可能性があります。
    • パフォーマンスが非常に重要な場合は、QGraphicsView::NoViewportUpdateに設定し、必要に応じて手動でviewport()->update()を呼び出すことも検討できますが、これは高度な制御が必要です。

回転後にクリック位置や座標変換がずれる

原因

  • ビューとシーンの座標系の理解不足
    QGraphicsViewはビューポート(ウィジェットの座標系)、ビュー(変換されたビューポートの座標系)、そしてシーン(シーン内のアイテムの座標系)の3つの異なる座標系を持っています。回転はビューの変換行列を操作するため、マウスイベントの座標を正しくシーン座標に変換しないと、意図しない結果になります。
  • QGraphicsItemの座標系
    QGraphicsItemの座標は常に自身のローカル座標系で扱われます。親アイテムやビューの変換は、アイテムの描画にのみ影響し、アイテムの内部的な座標には影響しません。この点を理解しておくことが重要です。
  • mapToScene()とmapFromScene()を適切に使う
    • マウスイベントの座標(ビューポート座標)をシーン座標に変換するには、QGraphicsView::mapToScene(event->pos()) を使用します。
    • シーン座標からビューポート座標に変換するには、QGraphicsView::mapFromScene(scenePos) を使用します。
    • 回転後もこれらのマッピング関数は正しく機能するように設計されていますが、複雑な変換を重ねた場合は注意が必要です。


QGraphicsView::rotate()は、QGraphicsView自体(ビューポート)の表示を回転させるためのメソッドです。シーン内のアイテムを個別に回転させるのではなく、ビュー全体の視点を回転させます。

基本的なビューの回転

最も基本的な例として、ボタンを押すたびにビューを一定の角度で回転させる方法を示します。

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QPushButton> // ボタンを追加するために必要

class MainWindow : public QMainWindow
{
    Q_OBJECT // シグナル/スロットを使用するために必要

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void rotateView(); // ビューを回転させるスロット

private:
    QGraphicsView *graphicsView;
    QGraphicsScene *graphicsScene;
    QPushButton *rotateButton;
    qreal currentRotationAngle; // 現在の回転角度を保持
};

#endif // MAINWINDOW_H

MainWindow.cpp

#include "MainWindow.h"
#include <QVBoxLayout> // レイアウトのために必要
#include <QGraphicsRectItem> // シーンに矩形を追加するために必要
#include <QGraphicsEllipseItem> // シーンに楕円を追加するために必要

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      currentRotationAngle(0.0) // 初期角度を0に設定
{
    // QGraphicsSceneの作成
    graphicsScene = new QGraphicsScene(this);
    // シーンにアイテムを追加
    graphicsScene->addRect(-50, -50, 100, 100, QPen(Qt::blue), QBrush(Qt::cyan)); // 中心に矩形
    graphicsScene->addEllipse(100, 50, 80, 80, QPen(Qt::red), QBrush(Qt::magenta)); // 少しずらした位置に楕円
    graphicsScene->addText("Hello Qt Graphics View!"); // テキスト

    // QGraphicsViewの作成
    graphicsView = new QGraphicsView(graphicsScene, this);
    graphicsView->setRenderHint(QPainter::Antialiasing); // アンチエイリアシングを有効にして滑らかに描画
    // 回転の中心をビューの中心に設定 (デフォルトですが明示的に)
    graphicsView->setTransformationAnchor(QGraphicsView::AnchorViewCenter);

    // 回転ボタンの作成
    rotateButton = new QPushButton("ビューを45度回転", this);
    // ボタンのクリックシグナルとスロットを接続
    connect(rotateButton, &QPushButton::clicked, this, &MainWindow::rotateView);

    // レイアウトの設定
    QWidget *centralWidget = new QWidget(this);
    QVBoxLayout *layout = new QVBoxLayout(centralWidget);
    layout->addWidget(graphicsView);
    layout->addWidget(rotateButton);
    centralWidget->setLayout(layout);
    setCentralWidget(centralWidget);

    setWindowTitle("QGraphicsView::rotate() の例");
    resize(600, 400); // ウィンドウサイズを設定
}

MainWindow::~MainWindow()
{
    // シーンとビューは親オブジェクトに管理されるため、明示的な削除は不要な場合が多いですが、
    // ここでは安全のため省略します。
    // `delete graphicsScene;` や `delete graphicsView;` は通常必要ありません。
}

void MainWindow::rotateView()
{
    // 現在の回転角度に45度加算
    currentRotationAngle += 45;
    // 360度を超えたら0に戻す(任意)
    if (currentRotationAngle >= 360) {
        currentRotationAngle -= 360;
    }

    // ビューを新しい角度に回転
    // QGraphicsView::rotate() は現在の変換に追加する形で回転します
    // 特定の角度に設定したい場合は、resetTransform()してから設定するか、
    // QTransform を使って setTransform() します。
    graphicsView->rotate(45); // 現在のビューの状態からさらに45度回転
    // もし特定の角度に設定したい場合は以下のようになります (複雑な変換がない場合)
    // graphicsView->resetTransform(); // いったん変換をリセット
    // graphicsView->rotate(currentRotationAngle); // 新しい角度に設定

    qDebug() << "ビューを回転: " << currentRotationAngle << "度";
}

main.cpp

#include <QApplication>
#include "MainWindow.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

説明
この例では、rotateButtonをクリックするたびに、graphicsViewが現在の状態から45度回転します。QGraphicsView::setTransformationAnchor(QGraphicsView::AnchorViewCenter)を設定することで、ビューの中心を基準に回転が行われます。これにより、ビュー全体が中央を軸にしてクルクルと回るように見えます。

マウスドラッグによるインタラクティブな回転

より実用的な例として、マウスのドラッグ操作によってビューを回転させる方法を考えます。この場合、カスタムのQGraphicsViewクラスを作成し、マウスイベントを処理する必要があります。

CustomGraphicsView.h

#ifndef CUSTOMGRAPHICSVIEW_H
#define CUSTOMGRAPHICSVIEW_H

#include <QGraphicsView>
#include <QMouseEvent> // マウスイベントのために必要

class CustomGraphicsView : public QGraphicsView
{
    Q_OBJECT

public:
    explicit CustomGraphicsView(QGraphicsScene *scene, QWidget *parent = nullptr);

protected:
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;

private:
    QPoint lastMousePos; // マウスの最後の位置を記憶
    bool rotating;       // 回転中かどうかを示すフラグ
};

#endif // CUSTOMGRAPHICSVIEW_H

CustomGraphicsView.cpp

#include "CustomGraphicsView.h"
#include <QDebug> // デバッグ出力のために必要

CustomGraphicsView::CustomGraphicsView(QGraphicsScene *scene, QWidget *parent)
    : QGraphicsView(scene, parent),
      rotating(false)
{
    // アンチエイリアシングを有効にして、回転時にギザギザにならないようにする
    setRenderHint(QPainter::Antialiasing);
    // ビューの中心を基準に変換が行われるように設定
    setTransformationAnchor(QGraphicsView::AnchorViewCenter);
}

void CustomGraphicsView::mousePressEvent(QMouseEvent *event)
{
    // マウスの左ボタンが押されたら回転を開始
    if (event->button() == Qt::LeftButton) {
        rotating = true;
        lastMousePos = event->pos(); // 現在のマウス位置を記憶
        event->accept(); // イベントを処理済みとしてマーク
    } else {
        QGraphicsView::mousePressEvent(event); // 親クラスのイベントハンドラを呼び出す
    }
}

void CustomGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
    if (rotating) {
        QPointF currentPos = event->pos();
        QPointF center = QPointF(viewport()->width() / 2.0, viewport()->height() / 2.0);

        // 前回と現在のマウス位置から、回転の中心(ビューの中心)からのベクトルを計算
        QLineF oldVec(center, lastMousePos);
        QLineF newVec(center, currentPos);

        // 2つのベクトルのなす角度を計算し、回転角度とする
        // なす角度はdegrees()で度数に変換
        qreal angle = newVec.angle() - oldVec.angle();

        // ビューを回転させる
        rotate(angle);

        lastMousePos = currentPos; // マウスの現在の位置を次回の計算のために記憶
        event->accept();
    } else {
        QGraphicsView::mouseMoveEvent(event);
    }
}

void CustomGraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton && rotating) {
        rotating = false; // 回転を終了
        event->accept();
    } else {
        QGraphicsView::mouseReleaseEvent(event);
    }
}

MainWindow.h (変更点のみ)

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsScene>
// CustomGraphicsViewを使用するように変更
#include "CustomGraphicsView.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    CustomGraphicsView *graphicsView; // ここをCustomGraphicsViewに変更
    QGraphicsScene *graphicsScene;
};

#endif // MAINWINDOW_H

MainWindow.cpp (変更点のみ)

#include "MainWindow.h"
#include <QVBoxLayout>
#include <QGraphicsRectItem>
#include <QGraphicsEllipseItem>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    graphicsScene = new QGraphicsScene(this);
    graphicsScene->addRect(-50, -50, 100, 100, QPen(Qt::blue), QBrush(Qt::cyan));
    graphicsScene->addEllipse(100, 50, 80, 80, QPen(Qt::red), QBrush(Qt::magenta));
    graphicsScene->addText("マウスでドラッグしてビューを回転!");

    // CustomGraphicsViewのインスタンスを作成
    graphicsView = new CustomGraphicsView(graphicsScene, this);

    // レイアウトの設定 (以前と同じ)
    QWidget *centralWidget = new QWidget(this);
    QVBoxLayout *layout = new QVBoxLayout(centralWidget);
    layout->addWidget(graphicsView);
    // rotateButtonは不要になるので削除するかコメントアウト
    // layout->addWidget(rotateButton);
    centralWidget->setLayout(layout);
    setCentralWidget(centralWidget);

    setWindowTitle("QGraphicsView::rotate() インタラクティブ回転の例");
    resize(600, 400);
}

MainWindow::~MainWindow()
{
    // デストラクタは変更なし
}

説明
この例では、CustomGraphicsViewというカスタムクラスを作成し、mousePressEventmouseMoveEventmouseReleaseEventをオーバーライドしています。

  • mouseReleaseEvent: マウスボタンが離されたときに回転を終了します。
  • mouseMoveEvent: rotatingフラグがtrueの場合、前回のマウス位置と現在のマウス位置から回転の角度を計算し、rotate()メソッドを呼び出してビューを回転させます。
  • mousePressEvent: 左クリックが押されたときに回転を開始するフラグを立て、マウスの位置を記録します。

この方法により、ユーザーはマウスをドラッグするだけでビューをインタラクティブに回転させることが可能になります。



主に以下の3つの主要な代替方法があります。

  1. QGraphicsView::setTransform() を使用する
  2. QGraphicsItem::setRotation() を使用する
  3. QGraphicsItem::setTransform() を使用する

それぞれの詳細を説明します。

QGraphicsView::setTransform() を使用する

QGraphicsView::rotate()は内部的にQGraphicsViewの持つ変換行列(QTransform)を操作しています。より複雑な変換(拡大、縮小、平行移動、回転を組み合わせるなど)を一度に適用したい場合や、現在のビューの変換を完全に制御したい場合は、QTransformオブジェクトを直接構築してQGraphicsView::setTransform()を使用するのが最も柔軟な方法です。

特徴

  • 回転の中心の制御
    QTransformrotate()メソッドも、回転の中心を明示的に指定できます。
  • 完全な制御
    現在のビューの変換状態を完全に置き換えることができます。
  • 柔軟性
    複数の変換(回転、拡大縮小、平行移動)を組み合わせて一度にビューに適用できます。

コード例

#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QPushButton>
#include <QVBoxLayout>
#include <QTransform> // QTransform を使用するために必要

// ... (MainWindow.h と main.cpp は前回の例とほぼ同じ)

// MainWindow.cpp 内の関連部分
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      currentRotationAngle(0.0) // 現在の回転角度を追跡
{
    graphicsScene = new QGraphicsScene(this);
    graphicsScene->addRect(-50, -50, 100, 100, QPen(Qt::blue), QBrush(Qt::cyan));

    graphicsView = new QGraphicsView(graphicsScene, this);
    graphicsView->setRenderHint(QPainter::Antialiasing);
    // setTransformationAnchor は QGraphicsView::rotate() と同じように影響します

    rotateButton = new QPushButton("ビューを特定の角度に設定 (QTransform)", this);
    connect(rotateButton, &QPushButton::clicked, this, [=]() {
        currentRotationAngle += 45;
        if (currentRotationAngle >= 360) {
            currentRotationAngle -= 360;
        }

        QTransform transform;
        // まず拡大縮小を適用する場合
        // transform.scale(1.0, 1.0); // 例: 拡大縮小なし
        // 次に回転を適用
        transform.rotate(currentRotationAngle);

        // ビューに新しい変換行列を適用
        graphicsView->setTransform(transform);

        qDebug() << "ビューを特定の角度に設定: " << currentRotationAngle << "度";
    });

    // ... レイアウト設定など (前回の例と同じ)
}

QGraphicsView::rotate() と QTransform::rotate() の違い

  • QTransform::rotate(angle) を使用してsetTransform(transform): QTransformオブジェクトをゼロから構築し、その中で回転を定義します。これにより、ビューの変換がそのQTransformで完全に置き換えられます。そのため、連続的に角度を加えていきたい場合は、現在の角度を保持する変数(例: currentRotationAngle)が必要になります。
  • QGraphicsView::rotate(angle): 現在のビューの変換に、指定されたangleだけさらに回転を追加します。

QGraphicsItem::setRotation() を使用する

この方法は、ビュー全体ではなく、シーン内の個々のアイテムを回転させたい場合に利用します。QGraphicsView::rotate()と最も混同されやすい部分です。

特徴

  • シンプル
    アイテムを回転させるための最も簡単な方法です。
  • アイテムのローカル座標系での回転
    アイテムの回転は、そのアイテム自身のローカル座標系(デフォルトではアイテムの中心)を基準に行われます。
  • 個別のアイテムの回転
    シーン内の特定のアイテムだけを回転させることができます。

コード例

#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QPushButton>
#include <QVBoxLayout>

// ... (MainWindow.h と main.cpp は前回の例とほぼ同じ)

// MainWindow.cpp 内の関連部分
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      itemRotationAngle(0.0) // アイテムの回転角度を追跡
{
    graphicsScene = new QGraphicsScene(this);

    // 回転させる矩形アイテムを作成
    QGraphicsRectItem *rectItem = new QGraphicsRectItem(-50, -50, 100, 100);
    rectItem->setPen(QPen(Qt::green));
    rectItem->setBrush(QBrush(Qt::lightGray));
    // アイテムの回転の中心を自身の中心に設定 (デフォルトですが明示的に)
    rectItem->setTransformOriginPoint(0, 0); // 矩形の中心を原点に

    graphicsScene->addItem(rectItem); // シーンにアイテムを追加

    graphicsView = new QGraphicsView(graphicsScene, this);
    graphicsView->setRenderHint(QPainter::Antialiasing);

    rotateButton = new QPushButton("アイテムを45度回転", this);
    connect(rotateButton, &QPushButton::clicked, this, [=]() {
        itemRotationAngle += 45;
        if (itemRotationAngle >= 360) {
            itemRotationAngle -= 360;
        }

        // アイテムを回転
        rectItem->setRotation(itemRotationAngle);

        qDebug() << "アイテムを回転: " << itemRotationAngle << "度";
    });

    // ... レイアウト設定など (前回の例と同じ)
}

説明
この例では、rectItemだけがボタンクリックによって回転します。ビュー自体は回転しません。複数のアイテムがある場合、それぞれのアイテムが独立して回転できます。

QGraphicsItem::setTransform() を使用する

QGraphicsView::setTransform() と同様に、QGraphicsItemにもsetTransform()メソッドがあります。これにより、個々のアイテムに対してより複雑な変換を適用することができます。

特徴

  • QGraphicsItem::setRotation()よりも柔軟
    setRotation()は単純な回転のみですが、setTransform()はより多くの変換を制御できます。
  • 個別のアイテムへの複雑な変換
    個々のアイテムに対して、回転だけでなく拡大縮小、平行移動などを組み合わせて適用できます。

コード例

#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QPushButton>
#include <QVBoxLayout>
#include <QTransform>

// ... (MainWindow.h と main.cpp は前回の例とほぼ同じ)

// MainWindow.cpp 内の関連部分
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      itemRotationAngle(0.0) // アイテムの回転角度を追跡
{
    graphicsScene = new QGraphicsScene(this);

    QGraphicsRectItem *rectItem = new QGraphicsRectItem(-50, -50, 100, 100);
    rectItem->setPen(QPen(Qt::darkCyan));
    rectItem->setBrush(QBrush(Qt::darkMagenta));
    // アイテムの変換の中心を自身の中心に設定 (デフォルトですが明示的に)
    rectItem->setTransformOriginPoint(0, 0);

    graphicsScene->addItem(rectItem);

    graphicsView = new QGraphicsView(graphicsScene, this);
    graphicsView->setRenderHint(QPainter::Antialiasing);

    rotateButton = new QPushButton("アイテムを特定の角度に設定 (QTransform)", this);
    connect(rotateButton, &QPushButton::clicked, this, [=]() {
        itemRotationAngle += 30; // 30度ずつ回転
        if (itemRotationAngle >= 360) {
            itemRotationAngle -= 360;
        }

        QTransform transform;
        // アイテムの回転の中心を指定したい場合、translateとrotateを組み合わせる
        // 例: アイテムの左上隅 (QPointF(-50,-50)) を中心に回転したい場合
        // transform.translate(-50, -50);
        // transform.rotate(itemRotationAngle);
        // transform.translate(50, 50);

        // setTransformOriginPoint() を使っていれば、単純に回転を適用するだけ
        transform.rotate(itemRotationAngle);

        // アイテムに新しい変換行列を適用
        rectItem->setTransform(transform);

        qDebug() << "アイテムを特定の角度に設定: " << itemRotationAngle << "度";
    });

    // ... レイアウト設定など (前回の例と同じ)
}

説明
この例もQGraphicsItem::setRotation()と同様に個々のアイテムを回転させますが、QTransformを使うことで、回転、拡大縮小、平行移動といった複数の変換を同時に適用したり、変換の順序を細かく制御したりできます。setTransformOriginPoint()を設定している場合、QTransform::rotate()はその設定された原点を基準に回転を行います。

メソッド対象目的柔軟性回転の中心の制御
QGraphicsView::rotate()ビュー全体ビューの視点(カメラ)を回転させるsetTransformationAnchor()
QGraphicsView::setTransform()ビュー全体ビューの視点に複雑な変換を適用するQTransformで指定
QGraphicsItem::setRotation()個々のアイテム特定のアイテムをシンプルに回転させるsetTransformOriginPoint()
QGraphicsItem::setTransform()個々のアイテム特定のアイテムに複雑な変換を適用するsetTransformOriginPoint() または QTransformで指定