代码之家  ›  专栏  ›  技术社区  ›  Mateusz Andrzejewski

在QGraphicsView中创建自动滚动功能

  •  3
  • Mateusz Andrzejewski  · 技术社区  · 11 年前

    我有一个 QGraphicsView 和一个 QGraphicsScene 。根据用户输入 QGraphicsItem 可以放置在场景上。此项目既可选择也可移动。

    当场景大于视图滚动条时,将显示滚动条(设置为在必要时显示)。

    当用户将项目移动到视图边缘附近时,场景的宽度/高度会相应地拉伸——我正在使场景变大。

    问题是 当项目靠近视图边界时,如何强制滚动条与场景一起滚动? 功能我认为在任何图形编辑器中都很常见。在 MouseMoveEvent 在场景中,我正在使场景变大,迫使滑块移动并相应地更新可见的矩形。

    这并没有达到预期效果。即使考虑到滚动正在调整到新的场景大小,视图中也没有平滑的移动。有更好的方法吗?

    一些解释:

        itemUnderCursor = currently slected QGraphicsItem
        qgv = QGraphicsView
    

    代码段:

        // check if item is near the border
        QPointF point = itemUnderCursor->mapToScene(itemUnderCursor->boundingRect().topLeft());
        double delta = 0;
    
        if(point.x() < visibleRect.left())
        {
            // prevent from drawing outside the scene
            itemUnderCursor->setPos(visibleRect.left(), itemUnderCursor->scenePos().y());
    
            if(event->scenePos().x() < oldMousePos.x()-3)
            {
                // stretch the scene
                if(qgv->horizontalScrollBar()->value() <= 0)
                    setSceneRect(QRectF(QPointF(sceneRect().x() - 3, sceneRect().y()), sceneRect().bottomRight()));
                /*
                 * disable signals from DrawingArea in order to avoid
                 * recursive calls of mouseMoveEvent then enabling them
                 * back to handle the rest of events
                 */
                this->blockSignals(true);
                delta = point.x() - originalRect.left();
                qgv->horizontalScrollBar()->setValue(hScrollOriginalValue + delta);
            }
            oldMousePos = event->scenePos();
            this->blockSignals(false);
    
            // update the visible rectangle
            visibleRect = getVisibleRect(qgv);
        }
    
        if(point.x() + itemUnderCursor->boundingRect().width() > visibleRect.right())
        {
            // prevent from drawing outside the scene
            itemUnderCursor->setPos(visibleRect.right() - itemUnderCursor->boundingRect().width(), itemUnderCursor->scenePos().y());
            if(event->scenePos().x() > oldMousePos.x()+3)
            {
                // stretch the scene
                if(qgv->horizontalScrollBar()->value() >= 0)
                    setSceneRect(QRectF(sceneRect().topLeft(), QPointF(sceneRect().bottomRight().x() + 3, sceneRect().bottomRight().y())));
    
                /*
                 * disable signals from DrawingArea in order to avoid
                 * recursive calls of mouseMoveEvent then enabling them
                 * back to handle the rest of events
                 */
               delta = point.x() + itemUnderCursor->boundingRect().width() - originalRect.right();
               this->blockSignals(true);
               qgv->horizontalScrollBar()->setValue(hScrollOriginalValue + delta);
            }
            oldMousePos = event->scenePos();
            this->blockSignals(false);
    
            // update the visible rectangle
            visibleRect = getVisibleRect(qgv);
        }
    

    我正在对的顶部和底部边界执行相同的操作 Q图形视图 .

    1 回复  |  直到 11 年前
        1
  •  7
  •   Mateusz Andrzejewski    11 年前

    看起来我之前的尝试非常复杂,而解决方案实际上非常简单。

    与之前的代码不同,它足以编写:

    qgv->ensureVisible(itemUnderCursor);
    

    并确保 sceneRect() 不会设置任何值,而是由场景本身处理。

    这允许场景根据其上的项目自动调整其大小,并迫使滚动条在 QGraphicsView .