Re 1. QPainter
on anything (a widget, a pixmap, a printer,...) is a simple choice.
Re 2. Work on pixels in the QImage
, then draw the image on a painter.
Re 3. Painting on a widget is sufficient. You can base your widget on QAbstractScrollArea
.
The biggest point of the Graphics View Framework is interactivity with items in the scene. It makes life much easier then, and should be used to one's advantage.
If your view is non-interactive, then the only benefit would be the binary space partitioning index that culls the amount of work needed to do partial updates or updates when zoomed in. Unless you allow zooming in/panning, or do partial changes, it's pointless, since Qt windows are double-buffered and you essentially never do partial painting. For partial changes, the changed items need to be reindexed unless their geometry remains constant.
With panning/zooming, you should only use the graphics view if you have no easy way of iterating a subset of items to be drawn. The "hard" but generic way of doing it is to have a BSP index, and the Graphics View system provides this. I think in your case it should be easy to iterate over items/primitives that are within a given scene rectangle.
For drawing using QPainter
, it doesn't matter really what you draw on, it's a minor detail. You can factor out your drawing into a class that holds the data that needs to be drawn, for example:
class IRenderable {
protected:
/// Implementation of rendering.
virtual void renderImpl(QPainter & painter, QRect target) = 0;
public:
/// Draws all data (or the current view of it)
/// on the \a target rectangle of the \a painter.
void render(QPainter & painter, QRect target) {
renderImpl(painter, target);
}
};
class IteratedFunctionSystem : public IRenderable {
... // members describing the IFS etc.
/// Draws the entire IFS on the \a target rectangle of the \a painter.
void renderImpl(QPainter & painter, QRect target) Q_DECL_OVERRIDE;
public:
...
};
You can then use it in a generic widget:
class RenderableVisualizer : public QWidget {
QSharedPointer<IRenderable> m_renderable;
void paintEvent(QPaintEvent * ev) {
QPainter painter(this);
m_renderable->render(painter, rect());
}
public:
RenderableVisualizer(
QSharedPointer<IRenderable> renderable, QWidget * parent = 0
) : QWidget(parent), m_renderable(renderable)
{}
};
This approach could be extended to add an option to RenderableVisualizer
to have a local backing store and render to it from a separate thread. It'd provide smoother GUI operation if the rendering were to be lengthy.