2016-08-01 1 views
0

Qt에서 미리 정의 된 이동 옵션을 사용한 후 객체 중심에 대한 객체 회전에 문제가 있습니다. QGraphicsRectItem을 만들고 ItemIsMovable 특성을 설정합니다. 회전은 잘 작동합니다 (마우스 왼쪽 버튼으로 클릭하고 항목 위로 드래그).QGraphicsItem을 ItemIsMovable 속성으로 이동 후 이동

이제 사각형을 이동 (마우스 왼쪽 버튼으로 끌기)하고 다시 회전 해보십시오. 회전이 잘못되었습니다. sceneBoundingBox(). normalize.center()를 사용하여 사각형의 중심을 계산합니다. 이동 후에 그 점을 그려 보면 올바른 위치에 있습니다.

저는 setOriginTransform과 QTransform 메서드를 모두 사용했습니다. 그들은 둘 다 저에게 동일한 결과를줍니다.

장면의 좌표계와 회전 좌표계에 대해 혼란스러워합니까? 이사 한 후에 어떻게 바뀌나요?

여기에는 문제를 보여주는 컴파일 가능한 헤더 파일과 소스 코드가 있습니다. Qt 5.7을 Mac에서 사용하고 있습니다. 회전은 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 #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

아이템 좌표계 항목 국부적이다. 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); 
}