根据左上角缩放旋转的项目会移动项目

时间:2015-09-02 14:51:55

标签: qt rotation transform scaling qgraphicsitem

我希望能够根据其中心旋转QGraphicsItem,并根据左上角进行缩放。

当我尝试组合旋转和缩放时,该项目显然也会移动......

#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsTextItem>

void testTransformations(QGraphicsScene* s)
{
    qreal angle = 30, scaleX = 2, scaleY = 1;
    // Reference rotated not scaled
    QGraphicsTextItem* ref = new QGraphicsTextItem("bye world");
    ref->setFont(QFont("Arial", 20));
    ref->setDefaultTextColor(Qt::green);
    s->addItem(ref);
    qreal center0X = ref->boundingRect().center().x();
    qreal center0Y = ref->boundingRect().center().y();
    QTransform t0;
    t0.translate(center0X, center0Y);
    t0.rotate(angle);
    t0.translate(-center0X, -center0Y);
    ref->setTransform(t0);

    // Reference scaled not rotated
    QGraphicsTextItem* ref1 = new QGraphicsTextItem("bye world");
    ref1->setFont(QFont("Arial", 20));
    ref1->setDefaultTextColor(Qt::yellow);
    s->addItem(ref1);
    QTransform t;
    t.scale(scaleX, scaleY);
    ref1->setTransform(t);

    // Rotate around center of resized item
    QGraphicsTextItem* yyy = new QGraphicsTextItem("bye world");
    yyy->setDefaultTextColor(Qt::red);
    yyy->setFont(QFont("Arial", 20));
    s->addItem(yyy);
    qreal center1X = yyy->boundingRect().center().x() * scaleX;
    qreal center1Y = yyy->boundingRect().center().y() * scaleY;
    // in my code I store the item size, either before or after the resize, and use it to determine the center - which is virtually the same thing as this for a single operation
    QTransform t1;
    t1.translate(center1X, center1Y);
    t1.rotate(angle);
    t1.translate(-center1X, -center1Y);
    t1.scale(scaleX, scaleY);
    yyy->setTransform(t1);

    // rotated around center of bounding rectangle
    QGraphicsTextItem* xxx = new QGraphicsTextItem("bye world");
    xxx->setDefaultTextColor(Qt::blue);
    xxx->setFont(QFont("Arial", 20));
    s->addItem(xxx);
    qreal center2X = xxx->boundingRect().center().x();
    qreal center2Y = xxx->boundingRect().center().y();
    QTransform t2;
    t2.translate(center2X, center2Y);
    t2.rotate(angle);
    t2.translate(-center2X, -center2Y);
    t2.scale(scaleX, scaleY);
    xxx->setTransform(t2);
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QGraphicsScene s;
    QGraphicsView view(&s);
    s.setSceneRect(-20, -20, 500, 500);
    view.show();
    testTransformations(&s);
    return app.exec();
}

结果:

enter image description here

  • 绿色旋转,未缩放(或缩放不同数量)
  • 黄色缩放,不旋转
  • 蓝色缩放,并按边界矩形的中心(未调整大小)旋转
  • 红色缩放并围绕中心旋转

现在很明显,转换操作正确 - 如果我调整项目的大小和旋转,我先得到黄色然后是红色项目。

然而,我需要的是,如果一个项目已经旋转(绿色)然后缩放,表现得像蓝色 - 在同一方向拉伸,没有跳跃,而如果一个项目首先缩放,然后旋转,表现像红色......更复杂的是,原始项目(绿色)可能已经应用了缩放,因此使用边界矩形的简单解决方案将无法正常工作。

我试图计算变化......总是有奇怪的结果。

是否可以根据左上角缩放旋转的项目,而不是移动它,同时还可以围绕其中心旋转它?

它可能需要增量转换,根据它们的应用顺序得到不同的结果会很奇怪。

编辑:我一直在尝试进行位置调整,因为转换失败了,但是我无法获得一个转换函数的公式,它将为我提供类型的平滑视觉转换:

1)旋转项目(固定到中心)
2)比例项目(固定在左上方)没有跳跃 3)旋转项目(固定到中心)

其中步骤2还包括位置偏移。我只是不知道该怎么做 我看待它的方式,在&#34; red&#34;的片段中。变换,我会在变换之前和之后添加mapToScene(somePoint),并根据结果执行校正(moveBy)。

这不是一个很好的修复,但仍然......如果我知道如何在调整大小后调整项目的位置,这样它就不会跳转,它仍然是一个修复...

2 个答案:

答案 0 :(得分:3)

好的,对于后期编辑感到抱歉,似乎无法在Qt中直接实现。

然而,您可以使用简单的三角法来计算在围绕0,0原点旋转时从中心偏移并手动移动项目以补偿位移。

想象一个圆心,中心为0,0,半径为从圆心到物品边界框中心的直线。当您围绕0,0原点旋转项目时,项目的边界框中心将始终位于圆上,因此您可以计算给定旋转角度的偏移,然后旋转并调整项目的位置以匹配中心其先前的州。

这是一个小插图,正如您所看到的,在旋转之后,项目被偏移移动,以使其看起来好像围绕其中心旋转而不是左上角。当然,由于原点仍为0,0,它将按照您的意图进行缩放。

enter image description here

编辑:更简单,没有触发,只使用Qt功能,此方法将围绕其中心旋转项目,而变换原点位于左上角:

static void offsetRotation(qreal angle, QGraphicsItem * i) {
    QPointF c = i->mapToScene(i->boundingRect().center());
    i->setRotation(angle);
    QPointF cNew = i->mapToScene((i->boundingRect()).center());
    QPointF offset = c - cNew;
    i->moveBy(offset.x(), offset.y());
}

然而,我注意到一些奇怪的事情 - 当原点设置在左上方时,根据我对图形设计软件的长期经验,缩放并不能使左上角与我预期的位置保持一致。相反,随着规模的增加,该项目将逐渐消失。原点似乎确实对缩放产生了一些影响,但我绝对不会用任何措施称它为足够的。因此,根据您想要实现的目标,您可能必须使用相同的偏移调整技巧进行缩放。当项目缩放时,它将继续报告相同的位置,但是如果您将其映射到场景,您将意识到它实际上发生了变化,因此您可以跟踪该变化并进行补偿,以便产生相应的{{1方法。

所有这一切都需要付出代价,为了保持视觉输出符合预期,你的坐标将最终成为整个地方的混乱。这可能会在以后证明是一个复杂的问题。一种解决方案是为您的项目创建自己的“公共”坐标,并在内部管理所有混乱以规范化最终结果。

希望其他人可以提供一个更清洁的解决方案,根据我对Qt的经验,似乎从事图形课程的人对图形工作流程几乎没有经验,毫无疑问他们是优秀的程序员,但最终的结果是Qt的图形类通常是反直觉的,甚至完全无法按照人们对专业图形软件的期望工作。也许一个更务实的头脑可能会为这个问题提供更好的补救措施。

答案 1 :(得分:0)

这是我尝试解决问题的方法 - 它有效,但它不是一个很好的解决方案:

  • 对于任何转化,我都会存储ID VERSION A B C ----------------------------------------- 1 2 NULL 'b' 'c' 2 2 'f' 'd' 'e' m31()
  • 如果转换是缩放,我会通过新旧m32()m31()
  • 之间的变化来抵消