From f47ee03ce3e0d4185707e909e89b3d93e9e67632 Mon Sep 17 00:00:00 2001 From: Gary Wang Date: Wed, 2 Oct 2019 16:04:50 +0800 Subject: [PATCH] fix bugs within scale and rotate --- graphicsview.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++---- graphicsview.h | 12 ++++++++++ mainwindow.cpp | 13 ++++++----- 3 files changed, 74 insertions(+), 10 deletions(-) diff --git a/graphicsview.cpp b/graphicsview.cpp index 9407d21..1626fe7 100644 --- a/graphicsview.cpp +++ b/graphicsview.cpp @@ -84,6 +84,48 @@ void GraphicsView::setScene(GraphicsScene *scene) return QGraphicsView::setScene(scene); } +qreal GraphicsView::scaleFactor() const +{ + int angle = static_cast(m_rotateAngle); + if (angle == 0 || angle == 180) { + return qAbs(transform().m11()); + } else { + return qAbs(transform().m12()); + } +} + +void GraphicsView::resetTransform() +{ + m_scaleFactor = 1; + m_rotateAngle = 0; + QGraphicsView::resetTransform(); +} + +void GraphicsView::zoomView(qreal scaleFactor) +{ + m_scaleFactor *= scaleFactor; + reapplyViewTransform(); +} + +void GraphicsView::resetScale() +{ + m_scaleFactor = 1; + reapplyViewTransform(); +} + +void GraphicsView::rotateView(qreal rotateAngel) +{ + m_rotateAngle += rotateAngel; + m_rotateAngle = static_cast(m_rotateAngle) % 360; + reapplyViewTransform(); +} + +void GraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode) +{ + QGraphicsView::fitInView(rect, aspectRadioMode); + m_scaleFactor = scaleFactor(); +} + void GraphicsView::checkAndDoFitInView() { if (!isThingSmallerThanWindowWith(transform())) { @@ -132,16 +174,18 @@ void GraphicsView::wheelEvent(QWheelEvent *event) { m_enableFitInView = false; if (event->delta() > 0) { - scale(1.25, 1.25); + zoomView(1.25); } else { - scale(0.8, 0.8); + zoomView(0.8); } } void GraphicsView::resizeEvent(QResizeEvent *event) { if (m_enableFitInView) { - if (isThingSmallerThanWindowWith(QTransform()) && transform().m11() >= 1) { + QTransform tf; + tf.rotate(m_rotateAngle); + if (isThingSmallerThanWindowWith(tf) && scaleFactor() >= 1) { // no longer need to do fitInView() // but we leave the m_enableFitInView value unchanged in case // user resize down the window again. @@ -197,7 +241,7 @@ void GraphicsView::dropEvent(QDropEvent *event) } bool GraphicsView::isThingSmallerThanWindowWith(const QTransform &transform) const -{qDebug() << sceneRect(); +{ return rect().size().expandedTo(transform.mapRect(sceneRect()).size().toSize()) == rect().size(); } @@ -238,3 +282,10 @@ void GraphicsView::setCheckerboardEnabled(bool enabled) setBackgroundBrush(Qt::transparent); } } + +void GraphicsView::reapplyViewTransform() +{ + QGraphicsView::resetTransform(); + scale(m_scaleFactor, m_scaleFactor); + rotate(m_rotateAngle); +} diff --git a/graphicsview.h b/graphicsview.h index d81bef7..bee2bed 100644 --- a/graphicsview.h +++ b/graphicsview.h @@ -20,6 +20,14 @@ public: GraphicsScene * scene() const; void setScene(GraphicsScene *scene); + qreal scaleFactor() const; + + void resetTransform(); + void zoomView(qreal scaleFactor); + void resetScale(); + void rotateView(qreal rotateAngel); + void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode = Qt::IgnoreAspectRatio); + void checkAndDoFitInView(); public slots: @@ -40,8 +48,12 @@ private: bool shouldIgnoreMousePressMoveEvent(const QMouseEvent *event) const; void setCheckerboardEnabled(bool enabled); + void reapplyViewTransform(); + bool m_enableFitInView = false; bool m_checkerboardEnabled = false; + qreal m_scaleFactor = 1; + qreal m_rotateAngle = 0; }; #endif // GRAPHICSVIEW_H diff --git a/mainwindow.cpp b/mainwindow.cpp index 35de353..910fc96 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -59,16 +59,17 @@ MainWindow::MainWindow(QWidget *parent) : m_bottomButtonGroup = new BottomButtonGroup(this); connect(m_bottomButtonGroup, &BottomButtonGroup::resetToOriginalBtnClicked, - this, [ = ](){ m_graphicsView->resetTransform(); }); + this, [ = ](){ m_graphicsView->resetScale(); }); connect(m_bottomButtonGroup, &BottomButtonGroup::zoomInBtnClicked, - this, [ = ](){ m_graphicsView->scale(1.25, 1.25); }); + this, [ = ](){ m_graphicsView->zoomView(1.25); }); connect(m_bottomButtonGroup, &BottomButtonGroup::zoomOutBtnClicked, - this, [ = ](){ m_graphicsView->scale(0.75, 0.75); }); + this, [ = ](){ m_graphicsView->zoomView(0.75); }); connect(m_bottomButtonGroup, &BottomButtonGroup::toggleCheckerboardBtnClicked, this, [ = ](){ m_graphicsView->toggleCheckerboard(); }); connect(m_bottomButtonGroup, &BottomButtonGroup::rotateRightBtnClicked, this, [ = ](){ - m_graphicsView->rotate(90); + m_graphicsView->resetScale(); + m_graphicsView->rotateView(90); m_graphicsView->checkAndDoFitInView(); }); @@ -87,7 +88,7 @@ void MainWindow::showUrls(const QList &urls) void MainWindow::adjustWindowSizeBySceneRect() { - if (m_graphicsView->transform().m11() < 1) { + if (m_graphicsView->scaleFactor() < 1) { // if it scaled down by the resize policy: QSize screenSize = qApp->screenAt(QCursor::pos())->availableSize(); QSize sceneSize = m_graphicsView->sceneRect().toRect().size(); @@ -120,7 +121,7 @@ void MainWindow::mousePressEvent(QMouseEvent *event) m_clickedOnWindow = true; m_oldMousePos = event->pos(); qDebug() << m_oldMousePos << m_graphicsView->transform().m11() - << m_graphicsView->transform().m22() << m_graphicsView->matrix().m11(); + << m_graphicsView->transform().m22() << m_graphicsView->matrix().m12(); event->accept(); }