问题
I've got an application where you can watch replays for a given 2D game :
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)
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.
Viewport update mode is set to QGraphicsView::BoundingRectViewportUpdate
.
Items index method is set to 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). 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...
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
OS : Windows XP SP3, did not test on other OS yet
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 :
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.
I compute all the clippings, and then render the scene in a 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).The replay is launched
I think Qt Graphics internals are messed up, but I can't figure out how to clean/reset it.
Here is an example of graphics (to illustrate what I mean by ground/sky). The map can be quite huge.
(source: kopasite.net)
回答1:
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.
回答2:
I believe this is similar to a problem I have had when working with lots 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.
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.
来源:https://stackoverflow.com/questions/11037837/qgraphicsscene-is-missing-a-particular-item-update