1
votes

I'm making fractal creator software. So I need one scene per fractal and these scenes need to be "layered" because of zooming rubber band.

I've already tried to write it the "widget" way, so I had one custom widget called "canvas". In my canvas class I overrided paintEvent, and inside this event I rendered current fractal. Everytime when somebody clicked to menu with another fractal, I called update() method and new fractal was rendered. To zooming I used overriding of mouse events and update() of canvas. At the first time I repainted the whole canvas, but it was very very slow. After that I repainted only the part under the rubber band, but still slow when I'd like to select some bigger area and other problems with repainting.

So I've looked for another way to do it. Layers. I've found the QStackedWidget, but I didn't find way how to make visible both of my layers and the top one to be transparent. After that, I've found QGraphicsScene and this seems to be the best way to do it. But I don't know the correct procedure to do it. Below are two procedures I'm thinking about:

  1. Create QGraphicsView
  2. Instead of the widget, the canvas will be QGraphicsScene
  3. I'll override some QGraphicsScene event (but I don't know which one - drawItems() is obsolete and override update() seems wrong to me, but maybe...)
  4. When other fractal will be chosen, I'll repaint canvas by calling update() the same way as in my "widget" solution
  5. In the foreground layer will be zooming rubber band

or:

  1. Create QGraphicsView
  2. Instead of the widget, the canvas will be QGraphicsScene
  3. Every fractal will be the child of QGraphicsItem
  4. When other fractal will be chosen, I'll remove the old one fractal item and replace it by new one and probably call invalidate()
  5. In the foreground layer will be zooming rubber band - I think, that it's common behaviour of the QGraphicsScene isn't it?

Is one of my reasonings correct? Do you suggest anything else? Fractals are complicated in the calculations and It's very important to repaint only if it is necessary. Could you help me, please?

Thank you :-)

Edit: "zooming rubber band" explanation:

I'm sorry for my expression "zooming rubber band". It means scale (zoom) the area below the selection made by the rubber band - zooming the same way as in Photoshop CS5 (for example). And I'd like to know what part of the scene is repainted while selecting this way. If there is repainted whole scene, or the part of the scene below selected area, or there is nothing repainted and rubber band selection is done in separate layer.

I hope my explanation helped :-).

1

1 Answers

1
votes

In Qt, a QGraphicsScene can be thought of as a world of items, with a QGraphicsView as a window into that world. Therefore, you should be adding items to the QGraphicsScene, based on QGraphicsItem (or QGraphicsObject if you want signals and slots).

In your situation, I'd create a Fractal class that inherits from QGraphicsItem and add that to the scene. Ensure to override the necessary pure virtual functions such as boundingRect and paint.

Do not calculate the fractal code in the paint function. I suggest the Fractal class stores a QPixmap (or QImage if you're drawing at the pixel level) and render the fractal to this. Then perodically, in the paint function, the Fractal class would render the contents of the QPixmap with a call to painter->drawImage or painter->drawPixmap; whichever is relevant in this case.

As for zooming, your Fractal class can then response to being scaled, appropriately changing the rendering on the internal representation.