Understanding Rotation Points in Qt Widgets with QGraphicsRotation::origin


Understanding QGraphicsRotation and Origin

In Qt's graphics framework, QGraphicsRotation is a class that enables you to rotate items within a scene. It provides a transformation around a specified axis, allowing you to control how elements are rotated.

The origin property in QGraphicsRotation plays a crucial role in defining the point around which the rotation occurs. This point remains fixed relative to the item's parent while the rest of the item pivots during the rotation.

Default Origin and Rotation Direction

By default, the origin is set to QPointF(0, 0), which signifies the item's top-left corner as the rotation point. The angle property, also part of QGraphicsRotation, determines the rotation amount in degrees (clockwise by default). Negative values produce counter-clockwise rotation.

Setting the Origin

#include <QGraphicsRotation>
#include <QPointF>

// ...

QGraphicsRotation *rotation = new QGraphicsRotation();
rotation->setOrigin(QPointF(offsetX, offsetY));  // Set custom origin

In this example, offsetX and offsetY represent the horizontal and vertical offsets from the item's top-left corner, defining the new rotation point.

  • Rotation is clockwise by default, with negative angles for counter-clockwise.
  • You can set a custom origin using setOrigin().
  • The default origin is (0, 0), which is the item's top-left corner.
  • The origin property dictates the point that remains stationary during the rotation.
  • QGraphicsRotation is used for 2D rotations within a scene.


Example 1: Rotating a rectangle around its center

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsRotation>

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

    // Create a scene and a rectangle item
    QGraphicsScene scene;
    QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 50);
    scene.addItem(rect);

    // Create a rotation object and set the origin to the center of the rectangle
    QGraphicsRotation *rotation = new QGraphicsRotation();
    rotation->setOrigin(rect->boundingRect().center());  // Set origin to rectangle's center
    rotation->setAngle(45);  // Rotate by 45 degrees clockwise

    // Apply the rotation to the rectangle
    rect->setTransform(rotation->transformation());

    // Show the scene in a window
    QGraphicsView *view = new QGraphicsView(&scene);
    view->show();

    return app.exec();
}

In this example, the origin of the rotation is set to the center of the rectangle using rect->boundingRect().center(). This ensures that the rectangle rotates around its exact middle point.

Example 2: Rotating a group of items around a specific point

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsEllipseItem>
#include <QGraphicsRotation>
#include <QGraphicsItemGroup>

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

    // Create a scene, ellipse items, and a group
    QGraphicsScene scene;
    QGraphicsEllipseItem *ellipse1 = new QGraphicsEllipseItem(10, 10, 30, 20);
    QGraphicsEllipseItem *ellipse2 = new QGraphicsEllipseItem(50, 20, 20, 40);
    QGraphicsItemGroup *group = new QGraphicsItemGroup();
    group->addToGroup(ellipse1);
    group->addToGroup(ellipse2);
    scene.addItem(group);

    // Create a rotation object and set the origin to a custom point
    QGraphicsRotation *rotation = new QGraphicsRotation();
    rotation->setOrigin(QPointF(40, 30));  // Set origin to a specific point
    rotation->setAngle(30);  // Rotate by 30 degrees clockwise

    // Apply the rotation to the group of items
    group->setTransform(rotation->transformation());

    // Show the scene in a window
    QGraphicsView *view = new QGraphicsView(&scene);
    view->show();

    return app.exec();
}

This example demonstrates how to rotate a group of items (ellipse1 and ellipse2) around a specific point defined by QPointF(40, 30). The rotation object is applied to the group using group->setTransform().



Using QGraphicsTransform Directly

QGraphicsTransform offers a more comprehensive way to manipulate items in a scene, including rotation. You can set the rotation angle and define the translation (offset) to effectively control the rotation point.

#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QTransform>

int main() {
    // ... (scene and rectangle creation)

    // Create a transform object and set rotation and translation
    QTransform transform;
    transform.rotate(45);  // Rotate by 45 degrees clockwise
    transform.translate(-50, -25);  // Translate to create custom origin (offset)

    // Apply the transform to the rectangle
    rect->setTransform(transform);

    // ... (scene and view setup)
}

In this example, the translate() method is used within the QTransform to shift the item by -50 units horizontally and -25 units vertically, essentially creating a custom origin for the rotation.

Leveraging Item Anchoring

Qt provides anchoring mechanisms that allow you to position items relative to their parents or other items in the scene. You can strategically use anchoring to achieve a rotation effect that simulates a specific rotation point:

#include <QGraphicsScene>
#include <QGraphicsEllipseItem>
#include <QGraphicsItem>

int main() {
    // ... (scene and ellipse creation)

    // Set top and left anchors to a custom point (simulates origin)
    ellipse2->setFlag(QGraphicsItem::ItemIsMovable, false);  // Prevent unintended movement
    ellipse2->setAnchor(QGraphicsItem::AnchorPoint, QPointF(40, 30));

    // Rotate the ellipse around its top-left corner (anchored point)
    ellipse2->setRotation(30);

    // ... (scene and view setup)
}

Here, ellipse2 is anchored to a specific point (QPointF(40, 30)) using setAnchor(). Then, rotation is applied using setRotation(), which effectively rotates the ellipse around the anchored point.

  • Anchoring is useful when you want to dynamically position items relative to other elements in the scene and achieve a rotation effect based on an anchored point.
  • If you require more complex transformations involving scaling, shearing, or combined rotations and translations, QGraphicsTransform offers greater flexibility.
  • For simple rotations with a clear need to define the origin, QGraphicsRotation::origin is often the most straightforward choice.