Qt: 回転やグループ化にも対応!シーン座標系とアイテム座標系を繋ぐQGraphicsItem::mapRectFromScene()


QGraphicsItem::mapRectFromScene()は、シーン座標系で指定された矩形を、そのアイテムの座標系に変換するための関数です。つまり、シーン全体における矩形の位置と大きさを、そのアイテムにおける位置と大きさに変換します。

この関数は、アイテムの形状や変形の影響を受けます。例えば、アイテムが回転されている場合、矩形も回転されます。

使用方法

QGraphicsItem::mapRectFromScene()は以下の引数を取ります。

  • rect: シーン座標系における矩形を表すQRectFオブジェクト

この関数は、変換された矩形を返すQRectFオブジェクトを返します。

QRectF sceneRect(100, 50, 200, 100);
QRectF itemRect = item->mapRectFromScene(sceneRect);

このコードは、シーン座標系における(100, 50)左上隅、(200, 100)右下隅を持つ矩形を、itemアイテムの座標系に変換し、その結果をitemRectに格納します。

  • アイテムがシーンに属していない場合、QGraphicsItem::mapRectFromScene()は、矩形を変換しません。
  • アイテムがグループ化されている場合、QGraphicsItem::mapRectFromScene()は、グループ内のアイテム座標系に矩形を最初に変換し、その後、グループ座標系に変換します。
  • QGraphicsItem::mapRectFromScene()は、アイテムの形状と変形に影響されます。アイテムが回転されている場合、矩形も回転されます。
  • QRectFは、矩形を表すクラスです。
  • QGraphicsItemは、Qt Graphics View Frameworkにおけるグラフィカルアイテムを表すクラスです。
  • Qt Widgetsは、Qt GUIアプリケーション開発のためのフレームワークです。


#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>

class MyItem : public QGraphicsItem
{
public:
    MyItem()
    {
        // アイテムを 45 度回転させる
        setTransform(QTransform().rotate(45));
    }

protected:
    QRectF boundingRect() const override
    {
        // アイテムの境界矩形を返す
        return QRectF(0, 0, 100, 100);
    }

    void paint(QPainter *painter, const QStyleOptionGraphics *option, QWidget *widget) override
    {
        // アイテムを描画する
        painter->setBrush(Qt::red);
        painter->drawRect(0, 0, 100, 100);
    }
};

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

    // シーンを作成する
    QGraphicsScene scene;

    // アイテムを作成する
    MyItem *item = new MyItem;
    scene.addItem(item);

    // ビューを作成する
    QGraphicsView view(&scene);
    view.show();

    return app.exec();
}

このコードを実行すると、以下のようになります。

赤い四角形がアイテムを表し、45度回転されています。シーン座標系における矩形 (青色の四角形) は、アイテムの座標系に変換され、アイテムに沿って回転されます。

例2:アイテムをグループ化する

この例では、アイテムをグループ化し、シーン座標系における矩形をグループの座標系に変換します。

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>

class MyItem : public QGraphicsItem
{
public:
    MyItem()
    {
        // アイテムを 45 度回転させる
        setTransform(QTransform().rotate(45));
    }

protected:
    QRectF boundingRect() const override
    {
        // アイテムの境界矩形を返す
        return QRectF(0, 0, 100, 100);
    }

    void paint(QPainter *painter, const QStyleOptionGraphics *option, QWidget *widget) override
    {
        // アイテムを描画する
        painter->setBrush(Qt::red);
        painter->drawRect(0, 0, 100, 100);
    }
};

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

    // シーンを作成する
    QGraphicsScene scene;

    // アイテムを作成する
    MyItem *item1 = new MyItem;
    MyItem *item2 = new MyItem;

    // アイテムをグループ化する
    QGraphicsItemGroup *group = new QGraphicsItemGroup;
    group->addItem(item1);
    group->addItem(item2);

    // グループをシーンに追加する
    scene.addItem(group);

    // ビューを作成する
    QGraphicsView view(&scene);
    view.show();

    return app.exec();
}

赤い四角形がアイテムを表し、45度回転されています。青色の四角形は、アイテムをグループ化したグループの境界矩形を表します。シーン座標系における矩形 (緑色の四角形) は、グループの座標系に変換されます。

説明

  • 例2では、group->mapRectFromScene()を使用して、シーン座標系における矩形をグループの座標系に変換しています。
  • 例1では、item->mapRectFromScene()を使用して、シーン座標系における矩形をアイテムの座標系に変換しています。

これらの例は、QGraphicsItem::mapRectFromScene()関数の使用方法を理解するのに役立ちます。

  • コードを実行するには、Qt Creatorなどの開発環境


代替方法

以下に、QGraphicsItem::mapRectFromScene()の代替方法をいくつか紹介します。

  • 数学的な計算: 矩形の座標とアイテムの変換行列がわかっている場合は、数学的な計算を使用して矩形を直接変換できます。
  • QPainter::translate(): この関数は、ペイントルーチン内で矩形を移動するために使用できます。
  • QTransform::mapRect(): この関数は、QTransformオブジェクトを使用して矩形を変換します。QGraphicsItemtransform()関数を使用して、アイテムの変換を取得できます。

各方法の詳細

  • QTransform::mapRect():

この関数は、QTransformオブジェクトを使用して矩形を変換します。QTransformオブジェクトは、回転、移動、スケーリングなどの変換を表すことができます。

QTransform transform = item->transform();
QRectF itemRect = transform.mapRect(sceneRect);

このコードは、itemアイテムの変換を取得し、その変換を使用してシーン座標系における矩形をアイテムの座標系に変換します。

  • QPainter::translate():

この関数は、ペイントルーチン内で矩形を移動するために使用できます。

QPainter painter;
painter.translate(item->pos());
painter.drawRect(sceneRect);

このコードは、アイテムの位置にペインタを移動し、シーン座標系における矩形を描画します。

  • 数学的な計算:

矩形の座標とアイテムの変換行列がわかっている場合は、数学的な計算を使用して矩形を直接変換できます。

QRectF itemRect;
for (int i = 0; i < 4; ++i) {
    QPointF point(sceneRect.topLeft() + QPointF(sceneRect.width() * i / 4, sceneRect.height() * i / 4));
    QPointF transformedPoint = item->transform().map(point);
    itemRect.setTopLeft(itemRect.topLeft().x() + transformedPoint.x(), itemRect.topLeft().y() + transformedPoint.y());
    itemRect.setBottomRight(itemRect.bottomRight().x() + transformedPoint.x(), itemRect.bottomRight().y() + transformedPoint.y());
}

このコードは、シーン座標系における矩形の各頂点をアイテムの座標系に変換し、変換された頂点を使用してアイテムの座標系における矩形を計算します。

どの方法を選択すべきか

どの方法を選択するかは、状況によって異なります。

  • ペイントルーチン内で矩形を移動する必要がある場合は、QPainter::translate()を使用する必要があります。
  • より多くの制御が必要な場合は、QTransform::mapRect()または数学的な計算を使用する必要があります。
  • シンプルさを重視する場合は、QGraphicsItem::mapRectFromScene()を使用するのが最善です。
  • 上記の代替方法は、あくまでも例です。状況に応じて、他の方法も考えられます。