在Qt中使用预定义的移动选项后,我遇到了关于对象中心的对象旋转问题。我创建了一个QGraphicsRectItem并设置了ItemIsMovable属性。旋转工作正常(按住鼠标左键并拖动项目)。
现在移动矩形,(按住鼠标左键拖动)并再次尝试旋转。旋转不正确。我使用sceneBoundingBox()。normalize.center()计算矩形的中心。如果我在移动后绘制该点,则它位于正确的位置。
我尝试过setOriginTransform并使用QTransform方法。他们都给了我相同的结果。
我对场景的坐标系与旋转坐标系感到困惑吗?搬家后如何改变?
这是一个精简的可编译头文件和源代码,用于演示此问题。我在Mac上使用Qt 5.7。旋转在函数rotateItem(...)中计算,所有坐标都应在场景坐标系中。
#include <cmath>
#include <QApplication>
#include <QWidget>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QBrush>
#include <QPen>
#include <QGraphicsSceneMouseEvent>
#include "myrect.h"
// THIS IS THE PROBLEM FUNCTION
// calculate rotations about the center of a given shape item.
void rotateItem(QAbstractGraphicsShapeItem* shape, QPointF center,
QPointF moved, QPointF initial_pos)
{
// get the angle from the center to the initial click point
qreal init_x = initial_pos.x() - center.x();
qreal init_y = initial_pos.y() - center.y();
qreal initial_angle = std::atan2(init_y, init_x);
qreal x = moved.x() - center.x();
qreal y = moved.y() - center.y();
qreal mv_angle = std::atan2(y,x);
// get the changed angle
qreal angle = (mv_angle - initial_angle)*180/M_PI;
if (std::fabs(angle) > 360.0)
angle = 0.0;
// both transforms give the same result
QTransform xform;
xform.translate(center.x(), center.y());
xform.rotate(angle);
xform.translate(-center.x(), -center.y());
shape->setTransform(xform, false);
//shape->setTransformOriginPoint(center);
//shape->setRotation(angle);
}
MyRect::MyRect(qreal x, qreal y, qreal width, qreal height) :
QGraphicsRectItem(x, y, width, height)
{
mInitialPos.setX(0.0);
mInitialPos.setY(0.0);
mInitialCenter.setX(0.0);
mInitialCenter.setY(0.0);
}
void MyRect::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
//if (event->modifiers() == Qt::ControlModifier)
if (event->modifiers() == Qt::ShiftModifier)
{
// ALL COORDINATES ARE IN THE SCENE COORDINATE FRAME (is that a problem?)
mInitialPos = event->scenePos();
mInitialCenter = this->sceneBoundingRect().normalized().center();
}
else
QAbstractGraphicsShapeItem::mousePressEvent(event);
}
}
void MyRect::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (event->buttons() == Qt::LeftButton)
{
if (event->modifiers() == Qt::ShiftModifier)
{
// Call the rotation function
rotateItem(this, mInitialCenter, event->scenePos(), mInitialPos);
event->accept();
}
else
{
QAbstractGraphicsShapeItem::mouseMoveEvent(event);
}
}
}
void MyRect::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
QAbstractGraphicsShapeItem::mouseReleaseEvent(event);
}
QGraphicsItem* add_rectangle(QGraphicsScene* scene)
{
MyRect* rectangle = new MyRect(-50, 10, 80, 80);
QBrush red_brush(Qt::red);
QPen pen(Qt::black);
pen.setWidth(4);
rectangle->setBrush(red_brush);
rectangle->setPen(pen);
rectangle->setFlag(QGraphicsItem::ItemIsMovable);
scene->addItem(rectangle);
return rectangle;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
QGraphicsView* graphicsView = new QGraphicsView(&w);
graphicsView->setGeometry(0,0,500,500);
QGraphicsScene* scene = new QGraphicsScene(&w);
graphicsView->setScene(scene);
add_rectangle(scene);
w.show();
return a.exec();
}
这是精简对象头文件 #ifndef MYRECT_H #define MYRECT_H #包括 #include
class MyRect : public QObject, public QGraphicsRectItem
{
Q_OBJECT
public:
MyRect(qreal x, qreal y, qreal width, qreal height);
void mousePressEvent(QGraphicsSceneMouseEvent* event);
void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
private:
QPointF mInitialPos;
QPointF mInitialCenter;
};
#endif // MYRECT_H
答案 0 :(得分:0)
项目坐标系是项目的本地。 Qt文档说明了这一点,但可能不够明确,无法通过我的大脑。
角度旋转坐标系位于场景坐标系中。我不得不将项目平移坐标与角度旋转坐标分开。角度是关于center1计算的,项目围绕中心旋转。
因此rotateItem方法变为:
void rotateItem(QAbstractGraphicsShapeItem* shape, QPointF center1,
QPointF moved, QPointF initial_pos)
{
QRectF bbox = shape->boundingRect().normalized();
QPointF center = bbox.center(); // item translate
// get the angle from the center to the initial click point
qreal init_x = initial_pos.x() - center1.x();
qreal init_y = initial_pos.y() - center1.y();
qreal initial_angle = std::atan2(init_y, init_x);
qreal x = moved.x() - center1.x();
qreal y = moved.y() - center1.y();
qreal mv_angle = std::atan2(y,x);
// get the changed angle
qreal angle = (mv_angle - initial_angle)*180/M_PI;
if (std::fabs(angle) > 360.0)
angle = 0.0;
// both transforms give the same result
QTransform xform;
xform.translate(center.x(), center.y());
xform.rotate(angle);
xform.translate(-center.x(), -center.y());
shape->setTransform(xform, false);
}