Draw a tree with Qt - qt

I need to draw a tree with Qt,
I was thinking using QGraphicsScene and QGraphicsItem for the nodes. But as I want the nodes to be movable, so how do it the best way for the lines between the node ?
Any suggestions ?
Thx.

I would implement arcs as items as well, QGraphicsLine item in particular. The line could go between the centers of connected nodes.
Keep a reference to incident edges in the node item, and during node dragging update line nodes with:
edge->setLine(QLineF(node_center.x, node_center.y);

I suggest you use QML for drawing those kind of things (I hate QML language, but unfortunately it is the future in Qt for drawing high performance graphics, they are working hard on that and Qt5 will also be more QML-centric I guess). For drawing lines you can use rotated thin rectangles. See Rectangle.

Related

How expensive are QPainter::save() and QPainter::restore()?

I want to build a scene graph to store and manage my scene layout which will be painted using QPainter (like QPicture, but the layout should be modifiable).
The scene graph will contain nodes for transformations, clipping and primitives. The first two will need to store the current state of the painter to restore it afterwards. It seems natural to use QPainter::save() and QPainter::restore() respectively.
I am a bit concerned about the efficiency of these two functions. Qt's documentation gives no information here. Looking at Qt's source code, it seems
QPainter::save() copies every element of the state, e.g. the pen, the brush, the transformation, the clipping path, and many many more. It seems to me that storing the former state of the one or two relevant properties that I actually need by myself is far more efficient. Has anyone any experience with this?

Bad openGL performance with many QGLMaterial items

in a project I want to render a lot of shapes with different colors.
I created the color of the shape with a QGLMaterial and add the shape to the QGLBuilder with this commands:
//Build SceneNode
m_lpBuilder->newSection();
...
m_lpBuilder->currentNode()->setMaterialIndex(idxMaterial); //idx in range of 0 to 1000
m_lpBuilder->currentNode()->setEffect(QGL::LitMaterial);
when I only have a few colors (QGLMaterial) the scene is rendered very fast but with a large kind of colors it is very slow.
is there a way to improve this?
I really recommend you use OpenGL directly. It will be much more obvious how much each operation costs you.
Here it's likely that Qt changes a Uniform and calls DrawArrays each time it renders with a different material, while the correct way to do this is to make the color a vertex attribute and put all your geometry into the same VAO. Perhaps it's possible to achieve with Qt, but I don't know how.

Is openGl usefull to display a map?

I have to display a tiled map to display the result of a simulation
One can zoom/unzoom on the map, so if the zoom is far, there will be much more tiles displayed.
I am using QGraphicsPixmapItem to add the tiles to a QGraphicsScene.
I wonder whether openGl would be able to speed things up
I am using QGraphicsPixmapItem to add the tiles to a QGraphicsScene.
QGraphicsScene already uses methods like spatial subdivision (Kd trees) to determine which parts of a scene are visible and which not. In addition QGraphicsScene can use OpenGL as a rendering backend.
I strongly suggest you stick with QGraphicsScene, you'll hardly get more efficient than this, especially considering your next question:
I wonder whether openGl would be able to speed things up
Not if used naively. OpenGL is not a scene graph. I can't cull away and not issue drawing commands for geometry not visible. If you send it drawing commands it will process them. Unlike QGraphicsScene, which maintains scene data, OpenGL will carry out whatever drawing operation you ask it to do. Even if the final result may be invisible. Only in the very last processing steps (clipping, early fragment rejection) invisible fragments are discarded.

Qt - multiple layers containing a QGraphicsView in one 3D scene (QGLWidget)

I'm currently evaluating the possibilities to implement a navigable 3D scene which allows to render multiple 2D layers. To be a bit more precise, I would like to display multiple graphs in a 3D environment in order to pinpoint simularities and differences between those graphs. Considering the following screenshot, there would be two graphs (one black, one grey), which are equivalent - for different graphs, deviant nodes might, i.e, be highlighted in red.
I am working with Qt's Graphic View Framework and established an editable graph editor using QGraphicsScene and several QGraphicsItems, which I separately from this project.
Qt provides OpenGL support, e.g., the QGLWidget and I had a look at the provided examples. Given, that I have not worked with OpenGL (I did some work with Java3D though) I would love if some people can share their experience.
Several solutions came to my mind:
Render every QGraphicsView to a QPixmap and display them in 3D, which would make the graphs navigatable but would prohibit any picking of elements etc.
Create an equivalent 3D element for every 2D graph element and "transform" every QGraphicsView into an 3D representation. I guess this would be quite some work (espacially as I have not worked with OpenGL)
Maybe there is an easy way to "place" the QGraphicScenes, the view, or just the QGraphicsItems in a QGLWidget without many adaptions and still register the usual "mouseclickevents" etc.
For a first implementation a plain navigable "viewer" which displayes multiple graphs in different layers would sufficient. But I would like to keep it extendable in order to add, e.g., picking, in the future.
The Qt3D project provides a class called QGraphicsEmbedScene which does exactly what you are asking for.

Does the point lie in the region?

I am doing this in my paintEvent
painter.drawPie(rect, angle*16, 45*16);
But before drawing the pie I want to know whether the current mouse position lies under the pie region or not.
Mouse tracking is on. And I can get the mouseEvents. No problem from that side. But what is the math involved to know wheather the point lies inside the pie or not?
It's unfortunate that QPainterPath doesn't have an addPie() function. You can, however, use Qt's implementation of QPainter::drawPie() as a reference:
http://qt.gitorious.org/qt/qt/blobs/4.7/src/gui/painting/qpainter.cpp#line4439
You can essentially create the QPainterPath the same way they do it and call contains() on it.
I have not tried this, but you could try to intersect two QPainterPaths (one triangle and one circle) to get a QPainterPath for your pie-segment and then call QPainterPath::contains(QPointF&) with the mouse position as parameter.
Now that I write this, the check is probably easy to implement: if the point is inside the circle and inside the triangle, then it's inside the pie. Both subtests are easy to implement.

Resources