关于qt:QgraphicsView橡皮筋拖动效果缩放行为

QgraphicsView rubberbanddrag effects zooming behavior

我被这种奇怪的行为困住了,如果我启用橡皮筋拖动,滚轮事件不再在鼠标下放大。它会缩放,但与鼠标位置无关。如果我禁用其他事件,则 wheelEvent 可以正常工作。

我有一个继承 QGraphicsView 的自定义类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class MyGraphics : public QGraphicsView{

public :
    MyGraphics(QWidget *parent = NULL);

public slots:
     void zoomIn() { scale(1.2, 1.2); }
     void zoomOut() { scale(1 / 1.2, 1 / 1.2); }

protected :
   QRubberBand *rubberBand;
   QPoint       origin;
   QPointF      InitialCenterPoint;
   QPointF      CurrentCenterPoint;
   QPoint       rubberBandOrigin;
   bool         rubberBandActive;
   QPoint       LastPanPoint;
   int          _numScheduledScalings;

//if I uncomment these three event handlers, the wheelevent doesnt zoom properly!

 //  virtual void mousePressEvent(QMouseEvent *event);
 //  virtual void mouseMoveEvent(QMouseEvent *event);
 //  virtual void mouseReleaseEvent(QMouseEvent *event);
   virtual void wheelEvent(QWheelEvent *);
   virtual void resizeEvent(QResizeEvent *event);

};

构造函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
MyGraphics::MyGraphics(QWidget *parent) : QGraphicsView(parent){
    setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);

    this->installEventFilter(this);
    this->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    this->setResizeAnchor( QGraphicsView::AnchorUnderMouse );
    QGraphicsScene *graphScene = new QGraphicsScene(this);

    this->setScene(graphScene);
    QGraphicsItem* pEllipse = graphScene->addEllipse(0,100,50,50);
    QGraphicsItem* pRect = graphScene->addRect(200,100,50,50);

    pEllipse->setFlag(QGraphicsItem::ItemIsSelectable, true);
    pRect->setFlag(QGraphicsItem::ItemIsSelectable, true);

    setSceneRect(0, 0, 1000, 1000);
    rubberBandOrigin = QPoint(0,0);
}

事件处理程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
void MyGraphics::wheelEvent(QWheelEvent *event){
    if(event->delta() > 0){
        //Zoom in
        this->zoomIn();
    } else {
        this->zoomOut();
    }

}

/*
void MyGraphics::mousePressEvent(QMouseEvent *event)
{
        if (event->button() == Qt::MiddleButton) {
        rubberBandOrigin = event->pos();
        rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
        rubberBand->setGeometry(event->x(),event->y(),0, 0);
        rubberBand->show();
        rubberBandActive = true;
    }
if(event->button() == Qt::LeftButton){
    LastPanPoint = event->pos();
}


}

void MyGraphics::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() == Qt::MiddleButton && rubberBandActive == true){
        rubberBand->resize( event->x()-rubberBandOrigin.x(), event->y()-rubberBandOrigin.y() );
    }
    else{
        if(!LastPanPoint.isNull()) {
            //Get how much we panned
            QGraphicsView * view = static_cast<QGraphicsView *>(this);

            QPointF delta = view->mapToScene(LastPanPoint) - view->mapToScene(event->pos());
            LastPanPoint = event->pos();
        }
    }
}

void MyGraphics::mouseReleaseEvent(QMouseEvent *event)
{
   if (event->button() == Qt::MiddleButton){
        QGraphicsView * view = static_cast<QGraphicsView *>(this);

        QPoint rubberBandEnd = event->pos();

        QRectF zoomRectInScene = QRectF(view->mapToScene(rubberBandOrigin), view->mapToScene(rubberBandEnd));
        QPointF center = zoomRectInScene.center();

        view->fitInView(zoomRectInScene, Qt::KeepAspectRatio);
        rubberBandActive =  false;
        delete rubberBand;
    }
    else{
        LastPanPoint = QPoint();
    }
}
*/

知道我在哪里做错了或如何解决吗?


QGraphicsView::scale 函数的行为取决于鼠标位置。它由 QGraphicsView 在内部自动执行。由于您没有将鼠标位置传递给 scale 函数,我认为 QGraphicsView 会跟踪鼠标并自行记住最后一个位置。

通过重新实现鼠标事件处理程序,您已经获得了这种能力。视图无法再确定鼠标位置,因为它的原始处理程序没有被调用。

幸运的是,这个问题很容易解决。你需要在你自己之前调用基类实现:

1
2
3
4
void MyGraphics::mousePressEvent(QMouseEvent *event) {
  QGraphicsView::mousePressEvent(event);
  // your implementation goes here
}

这是 mousePressEvent 的示例,但您应该向所有事件处理程序添加类似的语句,除非您需要禁用某些默认行为。