QT - 无法使用 mouseMove 移动场景

QT - cant make scene move with mouseMove

我有简单的 cpp 代码。我想用鼠标移动移动 QGraphicsScene:

// MainWindow.cpp code ------------------------------

void MainWindow::initializeMainViewWidget() {
/* some code */
    itemsFrame->setLayout(layout);

    mView = std::make_unique<ui::MainView>();
    layout->addWidget(mView.get());

    mScene = std::make_unique<ui::MainScene>();
    mView->setScene(mScene.get());

    QObject::connect(mScene.get(), &ui::MainScene::openItem, this, &MainWindow::openUpdateItemDialog);

    mView->show();
}

// MainView.cpp code -------------------------------

void MainView::mousePressEvent(QMouseEvent *event) {
    if (event->button() == Qt::RightButton) {
        // Store original position.
        mPos0 = event->position(); //mPos0 is QPointF
        event->accept();
        setCursor(Qt::ClosedHandCursor);
        return;
    } else if (event->button() == Qt::LeftButton) {
        event->ignore();
    }
    QGraphicsView::mousePressEvent(event);
}


void MainView::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton) {
        event->ignore();
    } else if (event->buttons() & Qt::RightButton) {
        QPointF trans = event->position() - mPos0;
        mPos0 = event->position();
        event->accept();
        translate(trans.x(), trans.y());
        return;
    }
    QGraphicsView::mouseMoveEvent(event);
}

但是当我通过以下方式添加项目时: addItem(someQGraphicsItem);

项目已显示。我可以拖动它...但是不能用 RMB 和 mouseMove 移动场景。

我从 中提取了我的旧示例并添加了通过鼠标拖动来平移内容的代码:

#include <QtWidgets>

// class for widget to demonstrate zooming
class Canvas: public QGraphicsView {

  // variables:
  private:
    // start position for pan
    QPoint _posRMB;

  // methods:
  public: 
    // constructor.
    Canvas() = default;
    // destructor.
    virtual ~Canvas() = default;
    // disabled:
    Canvas(const Canvas&) = delete;
    Canvas& operator=(const Canvas&) = delete;

  protected:

    virtual void mousePressEvent(QMouseEvent *pQEvent) override
    {
      if (pQEvent->button() == Qt::RightButton) {
        _posRMB = pQEvent->pos();
        pQEvent->accept();
        setCursor(Qt::ClosedHandCursor);
      }
    }

    virtual void mouseMoveEvent(QMouseEvent *pQEvent) override
    {
      if (pQEvent->buttons() & Qt::RightButton) {
        // pos() -> virtual canvas, _posRMB -> virtual canvas
        QPointF delta = mapToScene(pQEvent->pos()) - mapToScene(_posRMB);
        // modify transform matrix
        translate(delta.x(), delta.y());
        _posRMB = pQEvent->pos();
        // force update
        update();
        pQEvent->accept();
      }
    }

    virtual void mouseReleaseEvent(QMouseEvent *pQEvent)
    {
      if (pQEvent->button() == Qt::RightButton) {
        unsetCursor();
      }
    }

    virtual void wheelEvent(QWheelEvent *pQEvent) override
    {
      //qDebug() << "Wheel Event:";
      // pos() -> virtual canvas
      QPointF pos = mapToScene(pQEvent->pos());
      // scale from wheel angle
      float delta = 1.0f + pQEvent->angleDelta().y() / 1200.0f;
      // modify transform matrix
      QTransform xform = transform();
      xform.translate(pos.x(), pos.y()); // origin to spot
      xform.scale(delta, delta); // scale
      xform.translate(-pos.x(), -pos.y()); // spot to origin
      setTransform(xform);
      // force update
      update();
      pQEvent->accept();
    }
};

QRectF toScr(QWidget *pQWidget, float x, float y, float w, float h)
{
  const int wView = pQWidget->width(), hView = pQWidget->height();
  const int s = wView < hView ? wView : hView;
  return QRectF(
    (0.5f * x + 0.5f) * s, (0.5f * y + 0.5f) * s,
    0.5f * w * s, 0.5f * h * s);
}

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // setup GUI
  Canvas canvas;
  canvas.setTransformationAnchor(QGraphicsView::NoAnchor);
  canvas.setDragMode(QGraphicsView::NoDrag);
  canvas.resize(256, 256);
  canvas.show();
  // prepare scene
  QGraphicsScene qGScene;
  qGScene.addRect(toScr(canvas.viewport(), -1.0f, -1.0f, 2.0f, 2.0f), QColor(0x000000u));
  qGScene.addRect(toScr(canvas.viewport(), -0.2f, -0.2f, 0.4f, 0.4f), QColor(0x00ff00u));
  qGScene.addRect(toScr(canvas.viewport(), -0.8f, -0.8f, 0.4f, 0.4f), QColor(0xff0000u));
  qGScene.addRect(toScr(canvas.viewport(), -0.8f, 0.4f, 0.4f, 0.4f), QColor(0x0000ffu));
  qGScene.addRect(toScr(canvas.viewport(), 0.4f, 0.4f, 0.4f, 0.4f), QColor(0xff00ffu));
  qGScene.addRect(toScr(canvas.viewport(), 0.4f, -0.8f, 0.4f, 0.4f), QColor(0xffff00u));
  canvas.setScene(&qGScene);
  // runtime loop
  return app.exec();
}

输出:

我努力了一段时间才得到它 运行 正如预期的那样,直到我意识到

QPointF delta = mapToScene(pQEvent->pos() - _posRMB); // Not working!

不同
QPointF delta = mapToScene(pQEvent->pos()) - mapToScene(_posRMB);

此外,禁用 QGraphicsView:

的自动适应视图很重要
  canvas.setTransformationAnchor(QGraphicsView::NoAnchor);

在重新考虑 OP 问题时,我意识到另一个可能的问题:
如果场景小于视图,它会自动对齐。 (涉及QGraphicsView::alignment。)

在我的演示会话中,我从放大开始,以防止出现此问题。

另一个选项,即使场景小于视图也可以拖动 - 可以通过显式设置 QGraphicsView::sceneRect 来调整场景大小。


滚动浏览文档时。的 QGrapicsView 我注意到:

QGraphicsView::dragMode

dragMode : DragMode

This property holds the behavior for dragging the mouse over the scene while the left mouse button is pressed.

This property defines what should happen when the user clicks on the scene background and drags the mouse (e.g., scrolling the viewport contents using a pointing hand cursor, or selecting multiple items with a rubber band). The default value, NoDrag, does nothing.

This behavior only affects mouse clicks that are not handled by any item. You can define a custom behavior by creating a subclass of QGraphicsView and reimplementing mouseMoveEvent().

我觉得值得一提。