Hello.
I took the code from the one other forum. This code makes resizeble rectangles. I corrected a little for displaying pictures.
if anyone knows, tell me how to calculate the position of the MovableCircle so that the initial aspect ratio is preserved.
I've implemented part of the algorithm for eBottomRight and eTopLeft, but it still works very bad and doesn't work for BottomLeft and TopRight points. I want that it will be look like Krita or PureRef resize behaviour.
Thanks for any help, regards max
calc part:
Code:
{ auto pos = mapToScene(event->pos() + _shiftMouseCoords); qreal xl = (pos.x() == 0) ? .1 : pos.x(); qreal yl = (pos.y() == 0) ? .1 : pos.y(); qreal arl = qAbs(xl / yl); if (circlePos_ == eBottomRight) { if (arl > aspectRatio_) { pos.setX(yl * aspectRatio_); } else { pos.setY(xl / aspectRatio_); } } if (circlePos_ == eTopLeft) { LOG_WARNING(logger, "Circle Pos: ", circlePos_, ", ", pos.x(), " ", pos.y()); LOG_WARNING(logger, "Init Aspect Ratio: ", aspectRatio_, ", Current AspectRatio:", arl); if (arl > aspectRatio_) { LOG_DEBUG(logger, "> Before: ", pos.x(), ", ", pos.y()); pos.setY(xl / aspectRatio_); LOG_DEBUG(logger, "> After: ", pos.x(), ", ", pos.y()); } else { LOG_DEBUG(logger, "< Before: ", pos.x(), ", ", pos.y()); pos.setX(yl * aspectRatio_); LOG_DEBUG(logger, "< After: ", pos.x(), ", ", pos.y()); } } setPos(pos); emit circleMoved(); }
MovableCircle class:
Code:
class MovableCircle : public QGraphicsObject { Q_OBJECT public: enum ECirclePos { eTopLeft = 0, eTopRight, eBottomRight, eBottomLeft, }; private: QPointF _shiftMouseCoords; private: double aspectRatio_; ECirclePos circlePos_; signals: void circleMoved(); }; QGraphicsObject(parent), aspectRatio_(ar), circlePos_(cp) { setFlag(ItemClipsToShape, true); } { qreal adjust = 0.5; 10 + adjust, 10 + adjust); } { 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->drawEllipse(-5, -5, 10, 10); } { _shiftMouseCoords = this->pos() - mapToScene(event->pos()); } { auto pos = mapToScene(event->pos() + _shiftMouseCoords); qreal xl = (pos.x() == 0) ? .1 : pos.x(); qreal yl = (pos.y() == 0) ? .1 : pos.y(); qreal arl = qAbs(xl / yl); if (circlePos_ == eBottomRight) { if (arl > aspectRatio_) { pos.setX(yl * aspectRatio_); } else { pos.setY(xl / aspectRatio_); } } if (circlePos_ == eTopLeft) { if (arl > aspectRatio_) { pos.setY(xl / aspectRatio_); } else { pos.setX(yl * aspectRatio_); } } setPos(pos); emit circleMoved(); } { Q_UNUSED(event); }
MoveItem class:
Code:
{ Q_OBJECT public: ~MoveItem(); signals: protected: private: QPointF shiftMouseCoords_; QImage qimage_; QPixmap pixmap_; uint64_t& zCounter_; MovableCircle *_topLeftCircle, *_topRightCircle, *_bottomLeftCircle, *_bottomRightCircle; QSizeF _size; QRectF rect_; public slots: }; { setZValue(zCounter_); _size = pixmap_.size(); rect_ = qimage_.rect(); setAcceptHoverEvents(true); double ar = _size.width() / _size.height(); // Top Left _topLeftCircle = new MovableCircle(MovableCircle::eTopLeft, ar, this); _topLeftCircle->setPos(0, 0); // Top Right _topRightCircle = new MovableCircle(MovableCircle::eTopRight, ar, this); _topRightCircle->setPos(_size.width(), 0); // Bottom Right _bottomRightCircle = new MovableCircle(MovableCircle::eBottomRight, ar, this); _bottomRightCircle->setPos(_size.width(), _size.height()); // Bottom Left _bottomLeftCircle = new MovableCircle(MovableCircle::eBottomLeft, ar, this); _bottomLeftCircle->setPos(0, _size.height()); // 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 }); } MoveItem::~MoveItem() { } { 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 qMin(_topLeftCircle->pos().y(), _bottomLeftCircle->pos().y()), distX, distY); } { painter->drawImage(boundingRect(), qimage_); painter->drawRect(boundingRect()); Q_UNUSED(widget); } { this->setPos(mapToScene(event->pos()+ shiftMouseCoords_)); } { setZValue(++zCounter_); shiftMouseCoords_ = (this->pos() - mapToScene(event->pos()))/scale(); if (event->button() == Qt::LeftButton) { if (event->modifiers() == Qt::ShiftModifier) { } else { } } } { if (event->button() == Qt::LeftButton) { if (event->modifiers() == Qt::ShiftModifier) { } else { } } }