PDA

View Full Version : Caching expensive graph but still painting on top of it



peanut_butter_31
19th February 2016, 15:13
Hi!

I'm writing an application which draws a graph then allows the user to make certain queries of the data through mouse events. For example, when the user moves her mouse over the graphed points, I update labels near the axes telling the user what the highlighted points are. Additionally I allow the user to draw lines or rectangles on top of the graph to measure the distance between points.

Currently my application redraws all the points of the graph on each paintEvent(QPaintEvent* e) call, as well as any lines or rectangles that the user desires, on each QMouseEvent (moves, clicks, drags, etc.). The graph itself does not change, but the lines and rectangles on top do.

The graph itself is expensive to compute, so I would like to speed up my application by drawing the graph once and drawing on top.

I tried using QPixmapCache to cache the graph, paint it on my widget, then paint again on top of it, but I couldn't get it working. Should I be painting the pixmap before or after painting my widget? Is this something that should work, or should I try something else? Should I try a similar approach with QImage? I was using the tutorial at https://doc.qt.io/archives/qq/qq12-qpixmapcache.html but it seems rather dated, and I'm wondering if anyone can advise or point me to newer material.

Thanks!
M

d_stranz
19th February 2016, 16:14
I would think it would be pretty straightforward:

1 - In the constructor for your widget, create an empty pixmap
2 - In the paint event, check for an empty pixmap, and if empty, paint into it then
3 - If the pixmap is not empty (or you just painted it in step 2), paint the pixmap on the widget
4 - Follow by painting any user-added features.

Because you paint the pixmap first, any user added items will be erased on each paint event, so your app needs to remember them and their positions. You could make this easy by deriving your main widget from QGraphicsView and making all of the user objects QGraphicsItems added to a scene.

You will also need to implement the resize event. In this, all you need to do is destroy the pixmap and create a new empty one. The next paint event will take care of painting it to the new size. If this is too slow for real-time resizing, you could do some tricks with timers and scaling the current image until the user has stopped resizing, then create a new pixmap with the proper size.

peanut_butter_31
19th February 2016, 19:31
Thanks! I did what you advised and got it working.