2

I have been trying to use QGraphicsScene to create editable grid using following code:

int w = 5;
int h = 5;
//QRect r(0, 0, w*1680, h*800);
//scene->setSceneRect(r);
//scene->setBspTreeDepth(5);
//scene->setItemIndexMethod(QGraphicsScene::NoIndex);
QTime t;
for(long i = 0; i < 800; ++i) {
    t.restart();
    for(long j = 0; j < 1680; ++j) {
        QGraphicsItem *item = scene->addRect(j*w, i*h, w, h, pen, brush);
        item->setFlag(QGraphicsItem::ItemIsSelectable, true);
    }
    qDebug() << "Elapsed Time: " << t.elapsed();
}
//scene->setItemIndexMethod(QGraphicsScene::BspTreeIndex);
setScene(scene);
//setSceneRect(0, 0, 200, 200);

As can be seen from the code, there are approximately 1 million rectangle in the scene. Time to add new item seems to increase polynomially rather than logarithmically as described in the Qt documentation. Am I doing something obviously wrong?

dipesh
  • 45
  • 1
  • 6
  • I dont really have an answer to your question, but I think QGraphicsScene isn't meant to handle that many objects efficiently. I would maybe look into using OpenGL to draw the grid by connecting vertices. By drawing rectangles like you are doing currently, each edge will overlap with another, and keeping track of the connections at the corners will be a nightmare. Vertices seems like a better approach – Alexander Kondratskiy Jan 13 '12 at 18:14
  • I removed the overlap by reducing the width and height of rectangle. Performance still is same as it was previously. About the number of items in a scene, Qt documentation claims the QGraphicsScene is able to process millions of items very efficiently. Even then, if the issue is simply due to the number of items, I will definitely look into OpenGL for rendering. Thanks for the feedback. – dipesh Jan 13 '12 at 18:41
  • What I meant about the overlaps, is that there is a lot of redundancy in generating rectangles for a grid. Since you're trying to get a grid, any grid corner should have at most 4 lines emanating from it. By using rectangles, since they overlap, you will have 8 lines, some overlapping each other. In addition, at the grid corner, a total of 4 rectangles overlap. If someone was to try and move that point somewhere else you would have to update those 4 rectangles, instead of just one point. Perhaps Qt can handle such complexity, but it seems a roundabout way of doing what you want. – Alexander Kondratskiy Jan 13 '12 at 19:30
  • Additionally- what are your requirements for the grid? Can you just expand/contract rows or columns, or move individual vertices to deform the grid? For the first case, all you need is a set of intersecting lines to represent the grid, and span the whole length and width. Resizing a column/row would just mean displacing a bunch of these lines. If you need to have a deformable mesh, like the second case, then lines won't suffice, and you will need vertices joined with line segments. What I'm trying to say, is that depending on your problem, there is some optimal way of representing the grid. – Alexander Kondratskiy Jan 13 '12 at 19:35
  • No, the grid is not deformable. Main requirement is to be able to change color and other properties of a grid cell. So, cells are selectable. Just the intersecting lines will not be enough in this case. Using vertices and indices in OpenGL might help. I don't know how item selection works in QGraphicsScene if I use OpenGL. I will have to look into that. On second thought, I might be better off using QPixmap :). – dipesh Jan 13 '12 at 20:00
  • Ah! that changes things. I'll post an answer with some suggestions. – Alexander Kondratskiy Jan 13 '12 at 20:07

2 Answers2

4

This answer is directed to the particular problem mentioned in the comments below the question- A static grid where various grid cells can be "selected".

The key idea here is that the grid is not deformable, and the selection of a cell is a "rare" occurance. An idea that comes to mind is to define the backgroundBrush property of the QGraphicsScene to draw the static grid for you, perhaps using a simple tile-able QPixmap. This is efficient as it is just a background to the scene and involves no dynamic objects.

To make cells selectable is to watch for mouse events in the scene, and when a user clicks somewhere in the scene, you can create a rectangle of your desired color in the appropriate location. This allows you to essentially have an infinite grid where any cell can be selected.

To watch mouse events, subclass QGraphicsScene and reimplement the eventFilter method where you will handle some of the mouse events for dealing with selections. You can now install this filter by calling the installEventFilter method of your scene.

Inside your eventFilter method, you will essentially look out for mouse events, and depending on their position create new colored rectangles at the appropriate location in the scene.

Hope this makes sense.

Alexander Kondratskiy
  • 4,156
  • 2
  • 30
  • 51
  • 1
    This was exactly what I was planning after your comments above. It seems I cannot vote up as I have less than 15 reps. Sorry. :( – dipesh Jan 13 '12 at 20:57
1

Setting itemIndexMethod to noIndex helps the item insertion performance. See: For QGraphicsScene using setZValue on a QGraphicsItem causes major slowdown

Community
  • 1
  • 1
Stephen Chu
  • 12,724
  • 1
  • 35
  • 46
  • Yes. As you can see from the code above, I have been playing around with both `itemIndexMethod`, `bspTreeDepth`. By setting the `itemIndexMethod` to `noIndex` improves the insertion performance. But then the interaction with the scene becomes very slow. And changing the `bspTreeDepth` has no effect on the performance. My main question was why the scene creation takes too long. – dipesh Jan 13 '12 at 19:14