Redrawing a single row of a QwtPlotSpectrogram
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
Re: Redrawing a single row of a QwtPlotSpectrogram
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
Re: Redrawing a single row of a QwtPlotSpectrogram
Thanks Uwe. I'll give that a try.
Re: Redrawing a single row of a QwtPlotSpectrogram
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
Re: Redrawing a single row of a QwtPlotSpectrogram
Quote:
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
Re: Redrawing a single row of a QwtPlotSpectrogram
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...
Re: Redrawing a single row of a QwtPlotSpectrogram
Got it working!! Very smooth scrolling animation now. Uwe, thanks so much for your help!
Re: Redrawing a single row of a QwtPlotSpectrogram
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?
Re: Redrawing a single row of a QwtPlotSpectrogram
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
b) Plot canvas
Code:
plot
->canvas
()->setPaintAttribute
(QwtPlotCanvas::PaintCached,
false);
plot
->canvas
()->setPaintAttribute
(QwtPlotCanvas::PaintPacked,
false);
c) Qt ( only supported on X11 )
Code:
plot->canvas()->setAttribute(Qt::WA_PaintOnScreen, true);
Another optimization on multicore systems is to render parts of the image parallel in several threads.
Uwe
Re: Redrawing a single row of a QwtPlotSpectrogram
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).