Setting offset between two rotating QGraphicsRectItems
-
I have a red rectangle (QGraphicsRectItem), which position and rotation depends on pressed keys (up, down, left, right, turn right, turn left). I want another - green rectangle to follow red's position and rotation, but with a certain offset, in this manner:
I'd like to know how to achieve it without making the red parent of the green. My code (withotu the desired offset) is:
Game::Game() { player->setRect(0,0,100,100); player->setBrush(Qt::red); player->setPos(400,300); this->addItem(player); player->setFocus(); rectItem->setRect(0,0,100,100); rectItem->setBrush(Qt::green); rectItem->setPos(400,330); this->addItem(rectItem); player->setZValue(10); rectItem->setZValue(1); player->setTransformOriginPoint(player->boundingRect().width()/2 , player->boundingRect().height()/2 ); rectItem->setTransformOriginPoint(player->transformOriginPoint()); } void Game::advance() { rectItem->setPos(player->pos().x(), player->pos().y()); rectItem->setRotation(player->rotation()); }
-
@JonB You’re right, Thanks, QGraphicsItemGroup did the trick. I just needed to set the transform origin point to the centre of the red rectangle. Now the desired effect is achieved by this code:
#include "game.h" #include <QGraphicsItemGroup> QGraphicsItemGroup* g = new QGraphicsItemGroup; Game::Game() { player = new QGraphicsRectItem(); rectItem = new QGraphicsRectItem(); m_view = new QGraphicsView(this); m_view->setSceneRect(QRectF(0,0,800,600)); this->setBackgroundBrush(Qt::black); m_view->setScene(this); m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); m_view->setViewportUpdateMode(QGraphicsView::NoViewportUpdate); m_view->show(); player->setRect(0,0,100,100); player->setBrush(Qt::red); player->setPos(400,300); player->setFocus(); rectItem->setRect(0,0,100,100); rectItem->setBrush(Qt::green); rectItem->setPos(400,330); this->addItem(g); player->setZValue(10); rectItem->setZValue(1); g->addToGroup(player); g->addToGroup(rectItem); g->setTransformOriginPoint(player->pos().x() + player->boundingRect().width()/2 ,player->pos().y() + player->boundingRect().height()/2); } void Game::advance() { } void Game::keyPressEvent(QKeyEvent *event) { switch(event->key()) { case Qt::Key_Left : g->moveBy(-5,0); break; case Qt::Key_Right : g->moveBy(5,0); break; case Qt::Key_Up : g->moveBy(0,-5); break; case Qt::Key_Down : g->moveBy(0,5); break; case Qt::Key_Q : g->setRotation(g->rotation()- 3); break; case Qt::Key_W : g->setRotation(g->rotation() +3); break; } update(); }
-
-
@JoeCFD „A QGraphicsItemGroup is a special type of compound item that treats itself and all its children as one item (i.e., all events and geometries for all children are merged together).” But i want the green item to follow the red, meaning movement is applied to the red only (player->moveBy(0,5); so on). If i add them both to a QGraphicsItemGroup, then id need to apply movement and rotation directly to the whole QGraphicsItemGroup. I could add the green to a QGraphicsItemGroup and give the Group the red as the parent, but i want to avoid parenting.
-
@black_gay said in Setting offset between two rotating QGraphicsRectItems:
If i add them both to a QGraphicsItemGroup, then id need to apply movement and rotation directly to the whole QGraphicsItemGroup
I don't follow. That is exactly right, and isn't it precisely what you want? Set up the red & green rectangles initially in their right positions, like the first picture, and from then on when you rotate the group they will rotate together like your other pictures show?
Otherwise if for some reason the movements/rotations must be applied to the red rectangle, and you do not want to use either parenting or grouping, then you will have to apply the necessary transformation to the green rectangle whenever the red one is moved?
-
@JonB You’re right, Thanks, QGraphicsItemGroup did the trick. I just needed to set the transform origin point to the centre of the red rectangle. Now the desired effect is achieved by this code:
#include "game.h" #include <QGraphicsItemGroup> QGraphicsItemGroup* g = new QGraphicsItemGroup; Game::Game() { player = new QGraphicsRectItem(); rectItem = new QGraphicsRectItem(); m_view = new QGraphicsView(this); m_view->setSceneRect(QRectF(0,0,800,600)); this->setBackgroundBrush(Qt::black); m_view->setScene(this); m_view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); m_view->setViewportUpdateMode(QGraphicsView::NoViewportUpdate); m_view->show(); player->setRect(0,0,100,100); player->setBrush(Qt::red); player->setPos(400,300); player->setFocus(); rectItem->setRect(0,0,100,100); rectItem->setBrush(Qt::green); rectItem->setPos(400,330); this->addItem(g); player->setZValue(10); rectItem->setZValue(1); g->addToGroup(player); g->addToGroup(rectItem); g->setTransformOriginPoint(player->pos().x() + player->boundingRect().width()/2 ,player->pos().y() + player->boundingRect().height()/2); } void Game::advance() { } void Game::keyPressEvent(QKeyEvent *event) { switch(event->key()) { case Qt::Key_Left : g->moveBy(-5,0); break; case Qt::Key_Right : g->moveBy(5,0); break; case Qt::Key_Up : g->moveBy(0,-5); break; case Qt::Key_Down : g->moveBy(0,5); break; case Qt::Key_Q : g->setRotation(g->rotation()- 3); break; case Qt::Key_W : g->setRotation(g->rotation() +3); break; } update(); }