在 QGraphicsView 中创建自动滚动功能

Posted

技术标签:

【中文标题】在 QGraphicsView 中创建自动滚动功能【英文标题】:Creating autoscroll feature in QGraphicsView 【发布时间】:2013-08-26 09:43:57 【问题描述】:

我有一个QGraphicsView 和一个QGraphicsScene。根据用户输入,一些QGraphicsItem 可能会被放置在场景中。该项目既可选择又可移动。

当场景大于视图滚动条时出现(它们被设置为在必要时显示)。

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

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

这不能按预期工作。即使卷轴正在调整到新的场景大小,视图中也没有平滑的移动。有没有更好的方法来做到这一点?

一些解释:

    itemUnderCursor = currently slected QGraphicsItem
    qgv = QGraphicsView

代码sn-p:

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

我对@9​​87654328@ 的顶部和底部边框做同样的事情。

【问题讨论】:

使用 QGraphicsView 中的 centerOn 函数将视口放置在特定区域 harmattan-dev.nokia.com/docs/platform-api-reference/xml/… @Wagmare 不会 centerOn() 将项目完全放在视图的中心吗?我需要提供一些相对于该项目的点,以便将项目本身保持在边界附近,对吧? 【参考方案1】:

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

不用之前的代码写就够了:

qgv->ensureVisible(itemUnderCursor);

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

这允许场景根据其上的项目自动调整其大小,并在QGraphicsView 的可见矩形之外强制滚动条跟随移动的项目。

【讨论】:

以上是关于在 QGraphicsView 中创建自动滚动功能的主要内容,如果未能解决你的问题,请参考以下文章

在 Flutter 中创建双向 PageView 滚动?

滚动其中一个时如何滚动多个QGraphicsView(无滚动条)

在 QGraphicsView 中滚动

QGraphicsView 自定义滚动条

我可以在 Learndash 课程中创建用于自动注册 WP 角色的功能吗?

滚动 QGraphicsView 和 QGraphicsScene