Hello!
I'm working on project focused on map similar to Google Maps. The goal is to display whole map in QGraphicsView widget. To do this I created a QGraphicsScene built of many QGraphicsPixmapItem items. Each item stands for one map tile (A small PNG graphic). Because map is quite large (it's square of about 512x512 tiles and more) I'm trying to load tiles on demand (when they're visible in QGraphicsView widget's viewport area).
Some parts of code:
I create all tiles (QGraphicsPixmapItem items) at the beginning and set them with "empty" QPixmap:
MapTile::MapTile(int zoomLevel, ...)
{
bool returnStatus (false);
returnStatus
= QFile::exists(this
->tilePath
);
if(!returnStatus)
{
qWarning("Faield to locate tile PNG!");
return;
}
this
->setPixmap
(QPixmap (256,
256));
this->setPos (this->pixelsPosition.getX(), this->pixelsPosition.getY());
}
MapTile::MapTile(int zoomLevel, ...)
{
bool returnStatus (false);
returnStatus = QFile::exists(this->tilePath);
if(!returnStatus)
{
qWarning("Faield to locate tile PNG!");
return;
}
this->setPixmap(QPixmap (256, 256));
this->setPos (this->pixelsPosition.getX(), this->pixelsPosition.getY());
}
To copy to clipboard, switch view to plain text mode
Then I add each tile to scene.
I created class based on QGraphicsView named MapView and overloaded resizeEvent() and scrollContentsBy() methods. Code sample below shows only scrollContentsBy(), resizeEvent() is analogous.
First thing, I map top-left and bottom-right corners of QGraphicsView object into scene coordinates (pointa, pointb). Later in first loop I unload (load "empty" pixmap) all items assigned to scene (I know, it's stupid to unload all tiles, but I will make this part of code smarter later). In next two nested loops I pick only items currently visible in QGraphicsView object and load pixmaps into them.
void MapView::scrollContentsBy ( int dx, int dy )
{
this->QGraphicsView::scrollContentsBy(dx,dy);
MapScene* currentScene = this->zoomLevelScenes [this->currentZoomLevel];
QPointF pointa
(this
->mapToScene
(0,
0));
// top-left QPointF pointb
(this
->mapToScene
(this
->height
(), this
->width
()));
//bottom-right QList<QGraphicsItem*> list = currentScene->items();
{
((MapTile*)item)->loadPixmap(false);
}
for (qreal x = pointa.x() - 300; x < pointb.x() + 300; x += 255)
{
for (qreal y = pointa.y() - 300; y < pointb.y() + 300; y += 255)
{
MapTile* tile ((MapTile*) currentScene->itemAt(x,y));
if (tile!=0)
tile->loadPixmap(true);
}
}
}
void MapView::scrollContentsBy ( int dx, int dy )
{
this->QGraphicsView::scrollContentsBy(dx,dy);
MapScene* currentScene = this->zoomLevelScenes [this->currentZoomLevel];
QPointF pointa (this->mapToScene(0, 0)); // top-left
QPointF pointb (this->mapToScene(this->height(), this->width())); //bottom-right
QList<QGraphicsItem*> list = currentScene->items();
foreach(QGraphicsItem* item, list)
{
((MapTile*)item)->loadPixmap(false);
}
for (qreal x = pointa.x() - 300; x < pointb.x() + 300; x += 255)
{
for (qreal y = pointa.y() - 300; y < pointb.y() + 300; y += 255)
{
MapTile* tile ((MapTile*) currentScene->itemAt(x,y));
if (tile!=0)
tile->loadPixmap(true);
}
}
}
To copy to clipboard, switch view to plain text mode
My MapTile::loadPixmap() method:
void MapTile::loadPixmap(bool status)
{
bool returnStatus (false);
if (status)
{
returnStatus = pixmap.load(this->tilePath);
if(!returnStatus)
{
qWarning("Faield to load tile PNG!");
return;
}
}
this->pixmapLoaded = status;
this->setPixmap(pixmap);
}
void MapTile::loadPixmap(bool status)
{
QPixmap pixmap (256, 256);
bool returnStatus (false);
if (status)
{
returnStatus = pixmap.load(this->tilePath);
if(!returnStatus)
{
qWarning("Faield to load tile PNG!");
return;
}
}
this->pixmapLoaded = status;
this->setPixmap(pixmap);
}
To copy to clipboard, switch view to plain text mode
Code seems to work fine, because folder with tiles has about 500 MB and my program after start use only about ~25 MB. I also see correct map in window (there are no blank tiles displayed). The problems is that when I scroll map or resize window program is slowly, but constantly allocating more and more memory (on single resize event it allocates another 0.2 - 0.4 MB of RAM). After some time of working with program it becomes serious.
Any idea what's wrong? I assume, that I'm doing something wrong, right? Or maybe I'm not aware of some data chaching method used in Qt? I worked a lot with GTK+ and i'm pretty new to Wt...
Bookmarks