【问题标题】:QGraphicsScene is missing a particular item updateQGraphicsScene 缺少特定项目更新
【发布时间】:2012-06-14 16:54:34
【问题描述】:

我有一个应用程序,您可以在其中观看给定 2D 游戏的回放:

基本上,车辆在地图上移动。视图以车辆为中心,因此地图在回放时滚动,类似于 Micro Machines(只是提供一个想法,实际游戏不是 Micro Machines )。


(来源:randomracket.com

在我的场景中,当车辆四处移动时,地图是静态的。回放的每一帧视图都在滚动,因此车辆居中。 出于性能原因,地图平铺在几个QGraphicsPixmapItems 中。

视口更新模式设置为QGraphicsView::BoundingRectViewportUpdate。 项目索引方法设置为QGraphicsScene::NoIndex

在大多数情况下,一切正常。但是当地图比平时大时,车辆不会更新。视图正在滚动,图块更新良好;但不是车辆,除非我通过放大/缩小触发完整的视口更新(所以我知道该项目定位良好)。

车辆的 boundingRect 永远设置一次,并且是有效的(见下文,以逻辑坐标给出)。我不在项目的边界矩形之外绘制。

调试输出的一些例子(只有第三个配置不起作用):

ok :
vehicle->boundingRect() : QRectF(-1.9391,-1.9391 3.8782x3.8782)
scene->sceneRect() : QRectF(-117.543,-38.3826 138.834x40.3217)
SCENE_CACHING : 85 tiles

ok :
vehicle->boundingRect() : QRectF(-2.88489,-2.88489 5.76979x5.76979)
scene->sceneRect() : QRectF(-68.8843,-18.2202 187.989x119.277)
SCENE_CACHING : 308 tiles

nok : vehicle won't update
vehicle->boundingRect() : QRectF(-3.45546,-3.45546 6.91092x6.91092)
scene->sceneRect() : QRectF(-64.2988,-107.802 188.927x187.445)
SCENE_CACHING : 506 tiles

我尝试调试更新通道,绘制事件确实排除了车辆所在的区域...

有人知道为什么更新会遗漏某个特定项目吗?

编辑:

Qt : 4.8.1,我也看到了以前版本的问题

操作系统:Windows XP SP3,尚未在其他操作系统上测试

我没有成功地用一个最小的例子重现这个问题。最小的例子就像预期的那样工作。在现实生活中,这是完成的:

  1. 地图是从文件中读取的。它由多达数百个界定地面/天空的多边形(每个多边形由多边形、边缘和顶点层以图形方式组成)、数千张图片和纹理(然后剪辑到地面或天空)以及其他一些项目组成。

  2. 我计算所有剪辑,然后在 QImage 中渲染场景。图像在添加到场景中的几个QGraphicsPixmapItems 中平铺,而以前的项目从场景中删除并删除(顺便说一句,当我没有删除和删除以前的项目时也会出现错误)。

  3. 回放启动

我认为 Qt Graphics 的内部结构搞砸了,但我不知道如何清理/重置它。

这是一个图形示例(用于说明我所说的地面/天空的含义)。地图可能非常大。


(来源:kopasite.net

【问题讨论】:

  • 如何滚动视图?你在用QGraphicsView::centerOn吗?
  • 不,我使用QGraphicsView 的滚动条来定位某些东西,like this
  • 我知道有很多问题要问,但是有什么方法可以发布一个可以复制问题的最小示例?另外,什么操作系统和 Qt 版本?
  • 除了QGraphicsScene::update()之外,您是否为车辆尝试过QGraphicsItem::update()?似乎出于某种原因,视图认为不需要重新绘制项目,可能是因为它的绘制位置没有改变。
  • 不幸的是,这无济于事。 @DaveMateer 我尝试做一个最小的例子,但我不知道它是否会重现问题。

标签: c++ qt qgraphicsview qgraphicsscene


【解决方案1】:

从上面收集我的评论作为答案:

您需要使用QGraphicsScene::invalidate(...) 使应重绘的场景部分无效。

【讨论】:

  • 感谢您的想法。有时阅读文档是不够的。更准确地说,我使用了QGraphicsScene::invalidate(bRect,ItemLayer),其中bRect 是我的项目在场景坐标中的边界矩形。还有ItemLayer,因为我不使用背景也不使用前景。
【解决方案2】:

我相信这类似于我在使用大量 QGraphicsItems 时遇到的问题。我最终通过精简屏幕上的 QGraphicsItems 数量来解决我的问题,并且不缓存不需要缓存的 QGraphicsItems。

检查这是否是您的问题的一种简单方法是:

vehicle->setCacheMode(QGraphicsItem::NoCache);

这应该会导致每次需要绘制车辆时都会调用它的绘制方法。

【讨论】:

  • 我尝试了您的建议(即使 Qt 的文档声明 默认模式是 NoCache),但没有成功。但是,您是对的,只有在涉及很多项目时才会发生这种情况。但它只是渲染一次背景,然后我删除所有无用的项目。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-15
  • 2019-11-07
  • 1970-01-01
  • 2022-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多