Diving into Qt's Graphics View Framework Tue, Aug 12 2014 AM
From Qt's Graphics View Framework webpage: "Graphics View provides a surface for managing and interacting with a large number of custom-made 2D graphical items, and a view widget for visualizing the items, with support for zooming and rotation."
Initial design without QGraphics
First off, I created a completely functional topology designer for PothosGui without using or even knowing about Qt's Graphics View Framework. I created a base class called GraphObject that understood bounding areas, rotation, selection, zIndex, movement, and clickable areas. The objects were drawn into a QImage and displayed into a QWidget. A tedious state machine trigged by mouse events controlled the selection and movement animations.
All of that worked, and I probably never would have changed it, except for the fact that I have begun designing the support for pothos-widgets. The Pothos widgets are blocks that contain a QWidget to be rendered inside a GraphDraw, possibly along side other blocks in the topology. When I started with the GraphObject API, I assumed that it would be easy to figure out how to render arbitrary QWidgets along side the graph elements. Now it was time to figure it out... And after a litte searching, I stumbled upon QGraphicsWidget and then QGraphicsScene and QGraphicsView.
Switching to QGraphics
So, I did a 24 hour coding hack-a-thon to refactor the graphics; and in the process I learned a lot about QGraphics.
Some wasted effort
It turns out that I could have saved myself some work and a bunch of tedium. Not that GraphObject was a complete waste either. Most of the logic in the subclasses GraphBlock, Breaker, and Connection remained. And GraphObject remained a good abstraction for dealing with the stuff outside of QGraphicsObject, like serialization, and comprehension of connectable areas for creating connections in the topology designer.
- removed most of the tedium around mouse clicks, highlighting, and selection
- QGraphicsView even has its own highlighty-draggy selection box called RubberBandDrag
- provides coordinate translation between visible widget and QGraphicsScene
- and of course, I can render and interact with a standard QWidget in the scene
And I'm sure that there is even more that I dont know about QGraphics that I will take advantage of in the future.
I was having a terrible time with the GraphConnections 1) not rendering across large distances and 2) being randomly not selectable. I must have twisted every knob trying to figure this one out. 5 hours later, here is the solution:
//required: BspTreeIndex is too smart for its own good, connections will not render properly this->scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
So BspTreeIndex or "Binary Space Partitioning tree" is a performance algorithm to reduce the rendering complexity. But in this case, removing it made things work and didnt seem to impact the responsiveness of the animation. I suspect BspTreeIndex is more useful in the case of 100s or even 1000s of QGraphicsObjects.