c++ 在图形视图中实现场景的自由拖动

wnvonmuf  于 2023-07-01  发布在  其他
关注(0)|答案(1)|浏览(122)

我想实现一个基于C++ Qt的图形视图的自由拖动功能。
但是,我需要在不更改sceneRect和不使用view->setDragMode(QGraphicsView::ScrollHandDrag)的情况下实现这一点,因为我的一些业务逻辑依赖于sceneRect进行计算。
下面的代码可以重现我目前面临的问题,同时仍然成功运行。

view.h:

#include <QGraphicsView>
#include <QMouseEvent>
#include <QWheelEvent>
#include <qscrollbar.h>
class CView : public QGraphicsView
{
    Q_OBJECT
public:
    CView(QWidget* parent = nullptr) : QGraphicsView(parent) {
        setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
        setResizeAnchor(QGraphicsView::AnchorUnderMouse);
    }

protected:
    void mousePressEvent(QMouseEvent* event) override {
        if (event->button() == Qt::LeftButton) {
            m_lastPos = event->pos();
        }

        QGraphicsView::mousePressEvent(event);
    }

    void mouseMoveEvent(QMouseEvent* event) override {
        if (event->buttons() & Qt::LeftButton) {
            QPoint delta = event->pos() - m_lastPos;

            QRectF sceneRect = this->sceneRect();
            sceneRect.translate(-delta);
            this->setSceneRect(sceneRect);

            ensureVisible(sceneRect);

            m_lastPos = event->pos();
        }

        QGraphicsView::mouseMoveEvent(event);
    }

    void wheelEvent(QWheelEvent* event) override {
        QPoint scrollAmount = event->angleDelta();

        double scaleFactor = 1.15;
        if (scrollAmount.y() > 0) {
            scale(scaleFactor, scaleFactor);
        }
        else if (scrollAmount.y() < 0) {
            scale(1.0 / scaleFactor, 1.0 / scaleFactor);
        }

        // QRectF sceneRect = this->sceneRect();
        // QPointF viewCenter = mapToScene(viewport()->rect().center());
        // sceneRect.moveCenter(viewCenter);
        // this->setSceneRect(sceneRect);

        event->accept();
    }

private:
    QPoint m_lastPos;
};

场景h:

#include <QObject>
#include <QGraphicsScene>

class CScene : public QGraphicsScene
{
    Q_OBJECT
public:
    CScene() {}

protected:
    void drawBackground(QPainter *painter, const QRectF &rect) override {
        QGraphicsScene::drawBackground(painter, rect);
        painter->fillRect(sceneRect(), Qt::black);
    }
};

main.cpp:

#include "View.h"
#include "Scene.h"
#include <QApplication>

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    CView* view = new CView;
    view->resize(600, 500);
    CScene* scene = new CScene;
    scene->setSceneRect(0, 0, 300, 200);
    view->setScene(scene);
    view->show();
    return a.exec();
}

我遇到了两个问题:

  • 当我开始拖动鼠标时,视图会跳转(我注意到如果滚动条没有隐藏,它们的值就会变成最大值。我不确定这是由于坐标问题还是因为我在mouseMoveEvent中添加了ensureVisible(sceneRect))。
  • 如果我将视图嵌入到一个小部件中,并在小部件中放置一个QPushButton,当我单击按钮并调用view->fitInView(sceneRect, Qt::KeepAspectRatio)时,场景的位置不在视图的中心。
yh2wf1be

yh2wf1be1#

我已经找出了问题的根源。
第一个问题确实是由于ensureVisible(sceneRect)函数而发生的,该函数旨在确保给定的矩形在视图中可见。
关于第二个问题,通过调用qDebug() << viewportTransform(),我发现m31m32(转换组件)发生了变化,导致了偏移问题。要解决这个问题,我需要做的就是将m31和m32设置为0。这可以通过使用QGraphicsView::setSceneRect(0, 0, width, height)来实现。

相关问题