Yeah sure. The editor I wrote had more than 1000 nodes which had probably 10 or more connections to each other, and I had zero performance issues. It looked beautiful
There are a few tricks you can do.
1. Enable caching on QGraphicsItems: self.setCacheMode(QtGui.QGraphicsItem.ItemCoordinateCache )
This allocates GPU memory, basically render targets, for your nodes to efficiently redraw it when needed and keeps it cached as long as the content has not changed.
2. Enable sort caching on QGraphicsScene: self.setSortCacheEnabled( True )
This will speed up parent-child related QGraphicsItems during interaction such as moving them around in the scene.
3. Enable background caching on QGraphicsView: self.setCacheMode( QtGui.QGraphicsView.CacheBackground )
This will allocate one render target for the entire background and reuse it on the GPU.
4. Set the cache size to be used by the pixmaps: QtGui.QPixmapCache.setCacheLimit(101200) # 100 mb GPU cache
This sets the maximum texture memory your software should use when caching on the GPU.
5. Set QGraphicsScene indexing to none: self.setItemIndexMethod( QtGui.QGraphicsScene.NoIndex )
This will speed up interactive scenes where stuff move around such as the user dragging nodes which in turn has children or bezier curve connections etc. Indexing is good for static scene that don’t change. This might give speed or might not. Try it.
6. Play around with ViewportUpdateMode on QGraphicsView: self.setViewportUpdateMode( … )
Here you can tell QGraphicsView how much to update the scene. Minimal, Smart, BoundingRect etc. Play around with these there is no magic choice.
7. Use as little QGraphicsItems as possible and handle the drawing yourself inside the paint method!
The GPU caching is very handy here since it allocates a render target per node which means it only needs to REDRAW the node if the CONTENT changes like within the paint method of QGraphicsItem. So you would draw the text, input knobs, output knobs, headers etc inside the paint method.
This is also true for your bezier curve connections, play around with drawing them yourself inside drawBackground vs using actual QGraphicsItems. I went with using drawBackground on QGraphicsScene as far as I can remember for the bezier curves.
8. Don’t trigger something that would redraw the entire QGraphicsScene.
Don’t do stuff like calling update on the QGraphicsView or QGraphicsScene to redraw everything. You shouldn’t need to anyway when you use methods such as paint on your nodes. If you are going to use paint(…) on QGraphcisItem be sure to reimplement shape() which is used to determine what parts only need to be redrawn in the scene and boundingRect for selection and interaction.
These are some stuff that came to my mind that I used at my old job while working on a node editor!
Another thing you can do which might not sound like a trivial task is to use the OpenGL widgets that come with Qt. Alot of people had success with it. Basically you make your own node scene with node items
But if you follow the advice above you shouldn’t have any problems really! OpenGL stuff should be a last resort thing where you really need every bit of performance.
Also not a performance related thing but more of a design choice. You should be able to connect your nodes, serialize, deserialize and stuff without a GUI being present. So design the connections, inputs, outputs, nodes with pure python or QObjects and then do the editor part.
Let the core API allow callback registration which the GUI uses to update itself (Observer Pattern).
This way adding a script editor to the GUI becomes a trivial task. Since the callbacks are already registered to the view (the GUI) any script editor executed stuff will automatically show up on the GUI. This way you can also record scripts and build templates and extend the GUI to automate common stuff and let users kinda build their own “lib” of actions. Also if you don’t like the GUI or rendering, you can easily change it without affecting the core.
Lycka till >_^