PDA

View Full Version : qt 4.4 Issue with too many QGraphicsItems



spawn9997
8th July 2009, 18:15
Hi all,

I am using a QGraphicsView to display anywhere from 1000 to 100,000+ items and I have figured out how to use QGraphicsItem::paint() to draw or not draw the items. This is pretty good except in the case of viewing the entire scene.
I have seen that even the chips example slows down when zoom is full. No problem, I have designed a pixmap that draws a simple representation of the items at a certain level.

Issue: Still slower (load, zoom, and pan wise) than I would like.

Setup: I have 2 QGraphicsItem's and they have children that are QGraphicsItems as well. These children are the ones being drawn. I have implemented that when the level of detail gets too low (zoomed out) the child items are not drawn but instead the parent items displays the aforementioned pixmap(s).

possible Problem: Child items must each call paint() which exits immediately. Still 100,000+ calls takes time.

Question: Is there anyway to, I don't know, maybe set the parent such that the child items paint() function is NOT called when it is not drawn?
-or- is it quicker to just hide them? (although I'd rather not hide them)


I have implemented cache of scene, item, pixmap, and view by which gave best performance.

thanx n advance,

JW
sw developer

pherthyl
10th July 2009, 00:51
Hi all,

I am using a QGraphicsView to display anywhere from 1000 to 100,000+ items and I have figured out how to use QGraphicsItem::paint() to draw or not draw the items. This is pretty good except in the case of viewing the entire scene.
I have seen that even the chips example slows down when zoom is full. No problem, I have designed a pixmap that draws a simple representation of the items at a certain level.

Issue: Still slower (load, zoom, and pan wise) than I would like.

Setup: I have 2 QGraphicsItem's and they have children that are QGraphicsItems as well. These children are the ones being drawn. I have implemented that when the level of detail gets too low (zoomed out) the child items are not drawn but instead the parent items displays the aforementioned pixmap(s).

possible Problem: Child items must each call paint() which exits immediately. Still 100,000+ calls takes time.

Question: Is there anyway to, I don't know, maybe set the parent such that the child items paint() function is NOT called when it is not drawn?
-or- is it quicker to just hide them? (although I'd rather not hide them)


I have implemented cache of scene, item, pixmap, and view by which gave best performance.

thanx n advance,

JW
sw developer

You can also try setting QGraphicsView::DontSavePainterState on your view (of course you'll have to save/restore the painter state yourself in your paint() functions. But when you do not paint anything, you will save yourself some 100k calls to save/restore which should help.

spawn9997
14th July 2009, 19:58
pherthyl: I have that flag set already in the view and I did notice a boost in speed. Thanks!

Since Last time I have reimplemented the QGraphicsScene::drawItems() function and this sped up redraw a bit (entirely skip drawing of child items when I only need to draw parent).
After testing, I have found that my drawing routine is moving very fast compared to the loading of the said 100,000-400,000+ items from the QAbstractTableModel. The model data is saved in a SQL database (I'm not working on that part so I'm not sure of the specifics of that database.
I guess now the question is how to get that data out in a fast way? For now, I just go through the list one at a time and create a QGraphicsItem and set the proper data. This process is taking 3.4 sec on avg. for 136331 items (tested!) For this same project it loads 2 types of data into objects; one is much larger than the other. The smaller set takes just 1.5 secs. and total time from click to the view being populated is around 7-8 secs.

If this were the largest project I'd be done; but, the largest project takes 3x as long to load.

is this good or not?
Also, should I open a new thread for this?


JW
sw developer

wysota
14th July 2009, 23:24
How do you populate the scene? Could we see the exact code?

spawn9997
5th August 2009, 21:41
Hello all,

Sorry for the long wait but other work calls. :)

This is one of the model functions I use to create items and populate the scene from. The other (I have 2 models loading for now) they all will most likely look exactly the same.
Main issue is shear size. We load .5 million items in the largest of projects.


void ShotGraphicsLayer::setShotModel(ShotModel * shotModel){

emit this->loadProgress(0);
layerRect.setSize(QSize(1,1));
int nlocs = 0, xColumn,yColumn,zColumn, lineCol;
int swathCol;
QString swathVal, lineVal;
float x_min, x_max,y_min, y_max;
float y_value, x_value;
//float z_value,z_min, z_max;

nlocs = shotModel->rowCount(QModelIndex());

// get column numbers
xColumn = shotModel->fieldIndex("x");
yColumn = shotModel->fieldIndex("y");
zColumn = shotModel->fieldIndex("z");

lineCol = shotModel->fieldIndex("line");
swathCol = shotModel->fieldIndex("swname");
// copy data

QModelIndex sgi_ndx, temp_y_ndx,row_ndx, line_ndx, swath_ndx;

int progress;
for (int ndx=0; ndx < nlocs; ++ndx) {

progress = (ndx*100)/nlocs;
if(progress%5==0){
emit loadProgress(progress);
}

row_ndx = shotModel->index(ndx,0,QModelIndex());
sgi_ndx = shotModel->index(ndx,xColumn,QModelIndex());
temp_y_ndx = shotModel->index(ndx,yColumn,QModelIndex());
line_ndx = shotModel->index(ndx,lineCol,QModelIndex());
swath_ndx = shotModel->index(ndx,swathCol,QModelIndex());

x_value = shotModel->data(sgi_ndx,Qt::DisplayRole).toDouble();
y_value = shotModel->data(temp_y_ndx,Qt::DisplayRole).toDouble();
lineVal = shotModel->data(line_ndx,Qt::DisplayRole).toString();
swathVal = shotModel->data(swath_ndx,Qt::DisplayRole).toString();

//z_values[ndx] = shotModel->data(sgi_ndx,Qt::DisplayRole).toDouble();
ShotGraphicsItem * sgi = new ShotGraphicsItem(this);

sgi->setIndex(row_ndx);
sgi->setPos(x_value,y_value);

ShotGroup temp;
temp.insert(lineVal,sgi);

lineGroup.insert(lineVal,sgi);

if (swathGroup.contains(swathVal)) // if old group, add new multimap to old one.
swathGroup[swathVal] += temp;
else
swathGroup.insert(swathVal,temp);

this->setNumber(ndx+1);
sgi->setToolTip(QString("Shot %1").arg(number));

if (ndx == 0) {
x_max = x_value;
x_min = x_value;
y_max = y_value;
y_min = y_value;
} else {
x_min = std::min(x_min,x_value);
y_min = std::min(y_min,y_value);
x_max = std::max(x_max,x_value);
y_max = std::max(y_max,y_value);
}
QRectF rect(0,0,25,25);
sgi->setRect(rect);
if (ndx == 0)
layerRect.setRect(rect.x(),rect.y(),rect.width(),r ect.height());

}


layerRect.setRect(x_min,y_min,fabs(x_max-x_min),fabs(y_max-y_min));
emit this->loadProgress(100);
}

Basically it is....
0) for each row in model
1) get data from model
2) create graphicsitem
3) load index (currently the model is not changing)
3.5) add item to group (QMap) for easier access.
4) set position and adjust boundingRect.

- This function is from a QGraphicsItem that acts as the parent for all of these items so I add the items to the scene through this item and this item to the scene through its parent.
So I have... singular item added to scene-> this item has 2 children -> and these two have many child items, each.

Anyway, can anyone see how to load the data from the model quicker or make better use of the model, let me (us) know.


spawn9997
sw developer

pherthyl
6th August 2009, 23:44
I would profile which part of that loading function is actually taking the most time..

Nothing obvious jumps out at me.. If you don't need the sorting in your map you can use a QHash, should have much faster insertion times.

spawn9997
2nd September 2009, 15:56
Sorry for the long get back... the function is just long because of the great number of items. I found that creating QGraphicsItem's takes a good amount of time and accessing the data from the model take time.
We decided to let the load time stand as it is under half a minute for the largest projects including the drawing of the final scene to the QGraphicsView. We did add a progress bar for the user's sake!! Thanks again.

JW
sw developer