如何在调整大小期间保持相同的场景部分?

Posted

技术标签:

【中文标题】如何在调整大小期间保持相同的场景部分?【英文标题】:How to keep the same scene portion in view during resize? 【发布时间】:2014-08-14 08:06:13 【问题描述】:

我正在使用QGraphicsView 来显示函数图之类的东西。 QGraphicsView 在调整大小期间保持其变换,因此场景的可见部分会发生变化。

我需要在调整大小期间保持视图完全相同 - 不必保持纵横比,因为我允许在 X 轴和 Y 轴上独立缩放。

这不起作用:

void resizeEvent(QResizeEvent *event) override

    QRectF rect = mapToScene(this->viewport()->rect()).boundingRect();
    QGraphicsView::resizeEvent(event);
    fitInView(rect);

问题在于获得正确的视图矩形。此解决方案在调整大小时缩小。

有什么简单的方法可以实现吗?

【问题讨论】:

【参考方案1】:

我遇到了完全相同的问题。当视图大小发生变化时,您需要手动scale 视图,并恢复旧的中心点。在python中:

def resizeEvent(self, event):
    w_ratio = self.rect().width() / event.oldSize().width()
    h_ratio = self.rect().height() / event.oldSize().height()
    self.scale(w_ratio, h_ratio)

    self.centerOn(self.old_center)

您显然需要更早地设置self.old_center,例如在showEvent()。如果用户可以翻译视图,您还需要在mouseReleaseEvent() 中更新self.old_center

def showEvent(self, event):
    self.old_center = self.mapToScene(self.rect().center())

def mouseReleaseEvent(self, event):
    super(MyView, self).mouseReleaseEvent(event)
    self.old_center = self.mapToScene(self.rect().center())

【讨论】:

【参考方案2】:

创建继承自QGraphicsView 的自定义类后,您应该在自定义QGraphicsView 中重新实现resizeEvent( QResizeEvent *event ),例如:

void MyView::resizeEvent(QResizeEvent *event)


    QRectF rect = this->scene()->itemsBoundingRect();
    fitInView(rect);

    QGraphicsView::resizeEvent(event);

这样视图将始终显示整个场景。 IE。如果改变了窗口大小并且调整了 graphicsView 的大小,场景就会被缩放,你可以适当地看到一切。

【讨论】:

这与我的问题中的代码几乎相同(因此它不起作用)。 不一样。你不要使用Qt::KeepAspectRatio参数,同样QGraphicsView::resizeEvent(event);应该在函数结束时调用。 我不需要保持纵横比 - 正如我在问题中所写的那样,我允许每个轴上的独立比例。我最后一次打电话给fitInView(),因为您需要先调整大小,然后将前一个视图矩形调整到调整大小的视口。顺便说一句,我尝试了您的解决方案。 @Johny 您可以使用QGraphicsScene::itemsBoundingRect 计算并返回场景中所有项目的边界矩形。此外,如果您不想保持纵横比,请忽略Qt::KeepAspectRatio。我已经更新了答案。 这与我想要的不同 - 这会改变视图。如果我放大了视图(以研究一些细节),这将再次缩小调整大小。【参考方案3】:

fitInView 的视图中保持这个视图可视化的场景矩形怎么样?

void resizeEvent(QResizeEvent *event) override

    QGraphicsView::resizeEvent(event);
    fitInView(this->sceneRect());

【讨论】:

我相信这将使整个场景可见,而不是保留场景的当前显示部分。【参考方案4】:

我意识到这已经很老了,但我遇到了同样的挑战并找到了一个行之有效的解决方案。

我认为问题在于在调整大小事件中,正在获取视口坐标(映射到场景)。在这种情况下,视口已经改变(因此显示的场景),然后调用 fitInView 并稍微更新了一些场景坐标,因此显示场景实际上发生了变化。这变成了类似级联的效果。

我们想要做的是在调整大小事件期间始终将 same 场景矩形传递给fitInView。当我第一次加载图像时,我可以通过在本地存储场景坐标来实现这一点,然后在任何时候显示的场景发生变化(平移/缩放/重置视图等)。然后当调用调整大小事件时,我们总是传递相同的场景坐标,而不会陷入那个变化循环。

【讨论】:

以上是关于如何在调整大小期间保持相同的场景部分?的主要内容,如果未能解决你的问题,请参考以下文章

在调整大小期间保持子类 QWidget 的纵横比

在 IB 中,当我调整父视图的大小时,如何让子视图保持与父视图相同的大小?

调整浏览器大小时,如何使部分中的对象保持居中?

在调整大小期间调整离子菜单

枕头调整图像大小 - 保持纵横比

调整大小时 QGraphicsView 中项目位置的边距