Unsolved 5 days. I have been trying to center a freakin QGraphicsItem hierarchy. They made this hard.
-
@enjoysmath said in 5 days. I have been trying to center a freakin QGraphicsItem hierarchy. They made this hard.:
Don't give me this, moveBy, setPos, setTransform crap. It does not work!
when it doesn't work, you are doing it wrong, obviously.
Easiest would be when you show some code. -
I posted the code. I put it all in one file since I couldn't upload a document zip. Run it, or let me know if it doesn't immediately run. Firs spread the control points in the view. Then try moving the rectangle itself by selecting any part of the rectangle that's not at a control point. The lower / upper / left or right corner gets sucked into the mouse cursor position. I'd like the same to happen but with the center of the boundingRect(), not the corner!
I have tried at least 100 "permutations" on how it would work from my perfect understanding of the coordinate transformation system. Much of them failed to have an effect on the corner thing. And when they really suck, the whole scene just blows up or the item jets off or starts shaking abrubtly. Why is it so hard to do this? That makes no sense to me.
-
How is the code above?
-
@enjoysmath
sry i am not very good with Python. Maybe someone else can help here?
When i spot something i let you know. -
@raven-worx Thanks. Anything you code in C++ I can convert to Python easily. I'm familiar with Python mostly, but have toiled in C++ / QtCreator.
This problem is not specific to Python, I am 100% confident that you will find the same graphics item "features" in an analogous C++ version.
-
@raven-worx In other words, given a graphics item hierarchy : A -> B -> C, where -> is "is a parent of", how would you let C move freely (control points), where B's boundingRect() is the minimal bounding rect of all control points C in B, and I want to keep B's boundingRect() appearing centered on A's position?
Hold on... that just gave me an idea.
K, stuck in same boat. Here is a Pain3D png of what I want for the control point drag action.
By "origin" in the image I mean
pos()
-
The (0,0) point inside a child is the same (0,0) point inside your parent.
Noticed, when you are trying to centralize an object in a
graphicsview
, you have to translate a half to left and top to keep it on center:
Rect(-5,-5,10,10) => Centralized Rect with Width and Height = 10 on position (0,0).By what i understand, you are trying to resize the parent by child position B -> C. I had a similiar problem in an old project. See an example.
I am not sure how you can achieve this goal on PyQt but i can give you an example on Cpp.
.h file
class MovableCircle : public QGraphicsObject { Q_OBJECT public: explicit MovableCircle(QGraphicsItem *parent = 0); private: QRectF boundingRect() const; QPainterPath shape() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); QPointF _shiftMouseCoords; signals: void circleMoved(); }; class BoundedRect : public QGraphicsObject { Q_OBJECT public: BoundedRect(QGraphicsItem *parent = 0); QRectF boundingRect() const; private: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); MovableCircle *_topLeftCircle, *_topRightCircle, *_bottomLeftCircle, *_bottomRightCircle; QSizeF _size; };
.cpp file
#include "moveitem.h" #include <QtMath> ////////////////////// /// Movable Circle ////////////////////// MovableCircle::MovableCircle(QGraphicsItem *parent) : QGraphicsObject(parent) { setFlag(ItemClipsToShape, true); setCursor(QCursor(Qt::PointingHandCursor)); } QRectF MovableCircle::boundingRect() const { qreal adjust = 0.5; return QRectF(-5 - adjust, -5 - adjust, 10 + adjust, 10 + adjust); } QPainterPath MovableCircle::shape() const { QPainterPath path; qreal adjust = 0.5; path.addEllipse(-5 - adjust, -5 - adjust, 10 + adjust, 10 + adjust); return path; } void MovableCircle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); painter->setBrush(QBrush(Qt::red)); painter->setPen(QPen(Qt::black)); painter->drawEllipse(-5, -5, 10, 10); } void MovableCircle::mousePressEvent(QGraphicsSceneMouseEvent *event) { _shiftMouseCoords = this->pos() - mapToScene(event->pos()); this->setCursor(QCursor(Qt::ClosedHandCursor)); } void MovableCircle::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { setPos(mapToScene(event->pos() + _shiftMouseCoords)); emit circleMoved(); } void MovableCircle::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED(event); this->setCursor(QCursor(Qt::PointingHandCursor)); } ////////////////////// /// Bounded Class ////////////////////// BoundedRect::BoundedRect(QGraphicsItem *parent) : QGraphicsObject(parent), _size(180, 180) // Using the Construtor to setup te variable { setFlag(QGraphicsItem::ItemIsMovable, true); // Top Left _topLeftCircle = new MovableCircle(this); _topLeftCircle->setPos(-_size.width()/2, -_size.width()/2); // Top Right _topRightCircle = new MovableCircle(this); _topRightCircle->setPos(_size.width()/2, -_size.width()/2); // Bottom Left _bottomLeftCircle = new MovableCircle(this); _bottomLeftCircle->setPos(-_size.width()/2, _size.width()/2); // Bottom Right _bottomRightCircle = new MovableCircle(this); _bottomRightCircle->setPos(_size.width()/2, _size.width()/2); // Signals // If a delimiter point has been moved, so force the item to redraw connect(_topLeftCircle, &MovableCircle::circleMoved, this, [this](){ _bottomLeftCircle->setPos(_topLeftCircle->pos().x(), _bottomLeftCircle->pos().y()); _topRightCircle->setPos(_topRightCircle->pos().x(), _topLeftCircle->pos().y()); update(); // force to Repaint }); connect(_topRightCircle, &MovableCircle::circleMoved, this, [this](){ _topLeftCircle->setPos(_topLeftCircle->pos().x(), _topRightCircle->pos().y()); _bottomRightCircle->setPos(_topRightCircle->pos().x(), _bottomRightCircle->pos().y()); update(); // force to Repaint }); connect(_bottomLeftCircle, &MovableCircle::circleMoved, this, [this](){ _topLeftCircle->setPos(_bottomLeftCircle->pos().x(), _topLeftCircle->pos().y()); _bottomRightCircle->setPos(_bottomRightCircle->pos().x(), _bottomLeftCircle->pos().y()); update(); // force to Repaint }); connect(_bottomRightCircle, &MovableCircle::circleMoved, this, [this](){ _bottomLeftCircle->setPos(_bottomLeftCircle->pos().x(), _bottomRightCircle->pos().y()); _topRightCircle->setPos(_bottomRightCircle->pos().x(), _topRightCircle->pos().y()); update(); // force to Repaint }); } QRectF BoundedRect::boundingRect() const { // Calculate the Bouding Rect by 4 Limit Points qreal distX = sqrt(pow(_topLeftCircle->x() - _topRightCircle->x(),2) + pow(_topLeftCircle->y() - _topRightCircle->y(),2)); // eucledian distance qreal distY = sqrt(pow(_topLeftCircle->x() - _bottomLeftCircle->x(),2) + pow(_topLeftCircle->y() - _bottomLeftCircle->y(),2)); // eucledian distance return QRectF(qMin(_topLeftCircle->pos().x(), _topRightCircle->pos().x()) , qMin(_topLeftCircle->pos().y(), _bottomLeftCircle->pos().y()), distX, distY); } void BoundedRect::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); painter->setBrush(QBrush(Qt::blue)); painter->setPen(QPen(Qt::black)); painter->drawRect(boundingRect()); // draw by boundingRect }
-
Thank you, I can definitely look through and understand your code.
-
Sadly, this doesn't resolve my issues. I'm still troubleshooting it.
Remember, I want pressing on the items to center the item on the mouse cursor.
-
@enjoysmath
We need more information...- Your image is very polluated and confused
- Try to describe what you pretent to achieve with this manipulation and maybe it can be clearier to understand.