QgraphicsView 橡皮筋拖动效果缩放行为

Posted

技术标签:

【中文标题】QgraphicsView 橡皮筋拖动效果缩放行为【英文标题】:QgraphicsView rubberbanddrag effects zooming behavior 【发布时间】:2013-06-28 11:45:18 【问题描述】:

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

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

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);

;

构造函数:

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);

事件处理程序:

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();
    

*/

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

【问题讨论】:

你知道graphicsView-&gt;setDragMode(QGraphicsView::RubberBandDrag)吗?您似乎正在尝试实施已经实施的内容。 是的,我知道。但也有橡皮筋,我想用橡皮筋选择一个区域,并用所选区域填充整个屏幕。我不知道如何通过 setDragMode(QGraphicsView::RubberBandDrag) 来进行。这就是我实现自定义橡皮筋拖动过程的原因。 我不明白这个问题,但尝试在单独的问题中用更多细节来描述它。可能这个问题有解决方案,你不必重新实现橡皮筋。 好吧,我不知道要提供什么详细信息。问题很简单。当我评论其他鼠标事件时,wheelevent 缩放效果很好(如谷歌地球),如代码所示。如果我取消注释这些,缩放在轮事件中无法正常工作。 我说的是您在之前的评论中提到的问题:'我想用橡皮筋选择一个区域并按所选区域填充整个屏幕'。 【参考方案1】:

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

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

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

void MyGraphics::mousePressEvent(QMouseEvent *event) 
  QGraphicsView::mousePressEvent(event);
  // your implementation goes here

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

【讨论】:

谢谢!如此简单的解决方案,但我在网上的任何文档中都找不到!

以上是关于QgraphicsView 橡皮筋拖动效果缩放行为的主要内容,如果未能解决你的问题,请参考以下文章

取消在微信里面上拉拖动或者下拉拖动看到的空白。(也是什么橡皮筋效果)

如何识别 QGraphicsView 鼠标移动事件?

QT:我需要通过 QGraphicsScene 获取添加到 QGraphicsView 的图像坐标

使用特定键盘键的 qt 橡皮筋选择

在 QGraphicsScene 中缩放和旋转的 QGraphicsPixmapItem 的奇怪绘图行为

重新实现 mousePressEvent 后无法在 QGraphicsView 中拖动项目