2016-08-01 29 views
0

Ich habe Probleme mit der Objektrotation um das Objekt-Center nach der Verwendung der vordefinierten Option in Qt bewegen. Ich erstelle ein QGraphicsRectItem und setze das ItemIsMovable Attribut. Die Rotationen funktionieren gut (Shift mit der linken Maustaste klicken und ziehen Sie den Gegenstand).Drehen Sie QGraphicsItem mit ItemIsMovable Attribut nach dem Verschieben

Jetzt bewegen Sie das Rechteck, (Shift linke Maustaste) und versuchen Sie es erneut zu drehen. Die Drehung ist falsch. Ich berechne die Mitte des Rechtecks ​​mit dem sceneBoundingBox(). Normalize.center(). Wenn ich diesen Punkt nach dem Zug zeichne, ist er am richtigen Ort.

Ich habe versucht sowohl setOriginTransform und mit der QTransform-Methode. Beide geben mir die gleichen Ergebnisse.

Bin ich verwirrt über die Koordinatensysteme der Szene im Vergleich zum Rotationskoordinatensystem? Wie ändert sich das nach dem Umzug?

Hier ist eine abgespeckte kompilierbare Header-Datei und Quellcode, der das Problem demonstriert. Ich benutze Qt 5.7 auf einem Mac. Die Rotationen werden in der Funktion rotateItem (...) berechnet. Alle Koordinaten sollten im Szenen-Koordinatensystem liegen.

#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(); 
} 

Hier ist die Objekt-Header-Datei abgespeckte #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 

Antwort

0

Das Element Koordinatensystem ist lokal auf dem Posten. Die Qt-Dokumentation sagt dies, aber vielleicht nicht klar genug, um es durch mein Gehirn zu bekommen.

Das Winkeldrehungskoordinatensystem befindet sich im Szenen-Koordinatensystem. Ich musste das Item Koordinaten von den Winkeldrehungskoordinaten trennen. Der Winkel wird um Mittelpunkt1 berechnet und der Gegenstand wird um den Mittelpunkt gedreht.

So ist die Methode rotateItem wird:

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); 
}