PDA

View Full Version : Redrawing a single row of a QwtPlotSpectrogram



MSUdom5
27th November 2009, 19:37
I'm using the QwtPlotSpectrogram class to draw a spectrogram from a matrix of doubles. The matrix data is updating row-by-row and is updating at an extremely fast rate. Calling replot() works fine when my canvas is small, but when my canvas is large, replot() takes too long and can't keep up with the update rate of the canvas (i.e., plotting the updates is very jumpy and isn't smooth enought. Is there a way to selectively redraw parts of the canvas? For instance, if I have a canvas which is 1024x768 pixels, how could I redraw only the 1024 pixels in row N? I see there's a QPixmap object called paintCache in QwtPlotCanvas which seems like a good place to start looking, but I was wondering if anyone knew of an easy solution.

Thanks in advance,
MSUdom5

Uwe
28th November 2009, 16:16
Better overload QwtSpectrogram::renderImage and store the image of the first render operation. Then shift the cached image and calculate the additional rows only.

Uwe

MSUdom5
30th November 2009, 13:35
Thanks Uwe. I'll give that a try.

MSUdom5
30th November 2009, 21:51
I'm trying to implement this without changing any of the core Qwt source, but I've hit a snag:

How can I buffer the previous image? I can keep up with a QImage object "buffer_image" within my derived spectrogram class, but I can't change it in my overloaded renderImage since renderImage is a constant function. Is there any way I can get access to the currently drawn QImage from within QwtPlotSpectrogram? What would be the cleanest way to access (or store) the previously drawn image without changing any of the original Qwt source?

Thanks,
MSUdom5

Uwe
1st December 2009, 06:58
How can I buffer the previous image? I can keep up with a QImage object "buffer_image" within my derived spectrogram class, but I can't change it in my overloaded renderImage since renderImage is a constant function.

No, see: http://www.highprogrammer.com/alan/rants/mutable.html. Of course you can also do a const_cast for your this pointer.

Uwe

MSUdom5
1st December 2009, 13:17
Interesting, never used mutable before but it seems to work fine. However, I bet if my C++ professor were around, I'd probably get a slap on the hand...

MSUdom5
1st December 2009, 14:34
Got it working!! Very smooth scrolling animation now. Uwe, thanks so much for your help!

MSUdom5
2nd December 2009, 13:39
Although I've achieved my original goal, I'm now looking to generate large plots quicker and more efficiently. How much of a change would be involved to use OpenGL to paint plots instead of QPainter? I'm assuming I'll need to subclass QwtPlot? Uwe, any advice/direction?

Uwe
3rd December 2009, 14:41
First of all I would optimize the existing solution and turn all paint caches off, because you have your own image cache:

a) Spectrogram item

spectrogram->setCachePolicy(QwtPlotRasterItem::NoCache);

b) Plot canvas


plot->canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false);
plot->canvas()->setPaintAttribute(QwtPlotCanvas::PaintPacked, false);

c) Qt ( only supported on X11 )


plot->canvas()->setAttribute(Qt::WA_PaintOnScreen, true);

Another optimization on multicore systems is to render parts of the image parallel in several threads.

Uwe

MSUdom5
3rd December 2009, 18:19
Thanks! I'd already applied a) (the default is NoCache I think). I just applied b), and it sped things up a little. I'm using Windows (unfortunately), so c) doesn't apply.

For the most part, I'm getting the performance I need, so moving rendering to the GPU isn't absolutely necessary for me. My profiler says that most of the work is being done in qdrawhelper_p in some low-level math functions, so I don't think there's a higher level bottleneck. However, for a 1024x768 canvas, I'd like to be able to do 30 draws a second. Right now I can only get to ~20. (For smaller canvas, I have no problem with 30).