简体   繁体   English

QGraphicsScene缺少特定的项目更新

[英]QGraphicsScene is missing a particular item update

I've got an application where you can watch replays for a given 2D game : 我有一个应用程序,您可以在其中观看给定2D游戏的重放:

Basically, a vehicle is moving on a map. 基本上,车辆正在地图上移动。 The view is centered on vehicle so the map is scrolling as replay is playing, something Micro Machines -like (it's just to give an idea, the actual game is not Micro Machines ). 视图以车辆为中心,因此地图在播放重放时滚动,类似微机器 (仅仅是为了一个想法,实际的游戏不是微机器 )。


(source: randomracket.com ) (来源: randomracket.com

In my scene, the map is static while the vehicle is moving around. 在我的场景中,当车辆四处移动时,地图是静止的。 The view is scrolling for each frame of the replay, so that vehicle is centered. 视图正在滚动每个重播帧,以便车辆居中。 For performance reason, the map is tiled in several QGraphicsPixmapItem s. 出于性能原因,地图在几个QGraphicsPixmapItem平铺。

Viewport update mode is set to QGraphicsView::BoundingRectViewportUpdate . 视口更新模式设置为QGraphicsView::BoundingRectViewportUpdate Items index method is set to QGraphicsScene::NoIndex . 项索引方法设置为QGraphicsScene::NoIndex

In most cases, all is working fine. 在大多数情况下,一切都很好。 But when the map is larger than usual, the vehicle is not updated. 但是当地图比平时大时,车辆不会更新。 The view is scrolling and tiles are well updated; 视图滚动并且图块更新; but not the vehicle, unless I trigger a full viewport update by zooming in/out (so I know the item is well positioned). 但不是车辆,除非我通过放大/缩小触发完整的视口更新(所以我知道项目位置很好)。

The vehicle's boundingRect is set once for ever, and is valid (see below, given in logical coordinates). 车辆的boundingRect永久设置一次,并且有效(参见下面,以逻辑坐标给出)。 I do not paint outside item's bounding rect. 我不会在项目的边界矩形之外绘画。

some example of debug output (only third configuration does not work) : 调试输出的一些示例(仅第三个配置不起作用):

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

I tried to debug an update pass, and the paint event indeed excludes the region where vehicle is... 我试图调试更新传递,并且paint事件确实排除了车辆所在的区域......

Anyone know why an update could miss a particular item ? 任何人都知道为什么更新可能错过特定项目?

Edit : 编辑:

Qt : 4.8.1, and i've seen the problem with previous versions as well Qt:4.8.1,我也看到过以前版本的问题

OS : Windows XP SP3, did not test on other OS yet 操作系统:Windows XP SP3,尚未在其他操作系统上测试

I did not succeed in reproducing the problem with a minimal example. 我用一个最小的例子没有成功地重现这个问题。 The minimal example just work like it is expected to do. 最小的例子就像预期的那样工作。 In real life, here is what is done : 在现实生活中,这是做了什么:

  1. The map is read from a file. 从文件中读取地图。 It's composed of up to hundreds of polygons delimiting ground/sky (each one of which is graphically made of polygons, edges and vertices layers), thousands of pictures and textures which are then clipped to ground or sky, and some other items. 它由多达数百个界定地面/天空的多边形组成(每个多边形图形由多边形,边和顶点层组成),数千个图片和纹理然后被剪切到地面或天空,以及其他一些项目。

  2. I compute all the clippings, and then render the scene in a QImage. 我计算所有剪辑,然后在QImage中渲染场景。 The image is tiled in several QGraphicsPixmapItem s added to the scene, while the former items are removed from scene and deleted (btw the bug also occured when I didn't remove&delete former items). 图像在几个添加到场景中的QGraphicsPixmapItem平铺,而前一个项目从场景中删除并删除(顺便说一下,当我没有删除和删除以前的项目时也会出现错误)。

  3. The replay is launched 重播已启动

I think Qt Graphics internals are messed up, but I can't figure out how to clean/reset it. 我认为Qt Graphics的内部结构搞砸了,但我无法弄清楚如何清理/重置它。

Here is an example of graphics (to illustrate what I mean by ground/sky). 这是一个图形的例子(用来说明我的意思是地面/天空)。 The map can be quite huge. 地图可能非常庞大。


(source: kopasite.net ) (来源: kopasite.net

Picking up my comment from above as an answer: 从上面提出我的评论作为答案:

You need to use QGraphicsScene::invalidate(...) to invalidate the parts of the scene that should be redrawn. 您需要使用QGraphicsScene::invalidate(...)来使应重绘的场景部分无效。

I believe this is similar to a problem I have had when working with lots QGraphicsItems. 我相信这与我在处理大量QGraphicsItems时遇到的问题类似。 I eventually solved my problem by streamlining the amount of QGraphicsItems I had on the screen at any one time, and to not cache QGraphicsItems that did not need to be cached. 我最终通过简化屏幕上任何时候屏幕上QGraphicsItem的数量来解决我的问题,并且不缓存不需要缓存的QGraphicsItems。

An easy way to check if this is your problem would be: 检查这是否是您的问题的简单方法是:

vehicle->setCacheMode(QGraphicsItem::NoCache);

Which should cause the paint method on your vehicle to be called everytime it needs to be drawn. 这应该导致每次需要绘制车辆上的油漆方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM