PDA

View Full Version : QwtPicker RubberBand Performance



xerionn
28th April 2011, 02:37
Greetings,
I have a simple question so I can clear up some things.

I can see that in the QwtPicker there is a function called :
virtual void drawRubberBand( QPainter * ) const;
This function as the name suggests is responsible for drawing a rubberBand depending on the style used.

What i wanted to do is have rubberBand that is more like the common QRubberBand while additionally it covers the whole yAxisScale to select a region for either zooming or selection for example. So initially I've overwritten the drawRubberBand function and changed the size of my QRect to use the full height of my canvas. Initially i used QwtPainter::fillRect() but then i just went with QwtPainter::drawRect() by using the proper pens and brushes.

While this works fine and everything is good, its performance is not good as it feels slow and laggy. So instead I tested something else. If I use a QRubberBand and overwrite the mouse press, move and release event to handle the drawing properly I get a normal QRubberBand as I wanted while additionally the performance is really really good. I can then of course invTransform() my QRectF and do whatever I want with it.

So my question is why is it that the QRubberBand performance is much better compared to the qwt implementation of drawing ?

It seems that i forgot one more thing. Why is it that when I change the opacity of the painter with setOpacity() to something less than 0.8 (did not test thoroughly but 0.8 works while 0.7 does not) is like totally transparent ?

Thank you in advance,
Xerion

Uwe
28th April 2011, 07:32
So my question is why is it that the QRubberBand performance is much better compared to the qwt implementation of drawing ?
To be honest I didn't get what you do exactly in YourPicker::drawRubberband, so better post some code - best as a patch for one of the Qwt examples. Also add some more information about the Qwt version you are using and which operating system.

There is one performance issue in Qwt 5.2, that has been fixed in Qwt 6.0: when changing the mask of the rubberband while it is visible Qt triggers full repaints for the canvas instead of the region of the previous mask only. Even if this is doesn't mean a full replot, when the backing store of the canvas is enabled, it has the effect that the rubberband is behind fast mouse movements on my Atom system. In environments with a slow graphics system ( f.e Qt Embedded with an unaccelerated frame buffer ) this effect will be even worse.

But this effect doesn't depend on the type of rubberband.

Uwe

xerionn
28th April 2011, 08:09
My bad,
I guess I should have provided this info from the start along with a minimum working example.

So lets start. I have tested the above in both Windows Xp and 7 but not yet on Linux or Mac. I was using (till 5 minutes ago) qwt.6.0-rc5 but now I have moved to stable version 6 to be sure that its not something as silly as that.

I am providing 3 files that can just be placed over at the friedberg example to test. I have hacked quite a lot one of my classes that takes cares of panning, zooming and magnifying to leave it as small as possible in order to pass it over here. I should mention that I ripped code apart so if you see silly things like not checking the selected rectangle and all these kind of stuff please ignore it. Also don't expect to see anything happening after you relaese the mouse hehe, but have a look at the difference of performance in mouse left click and right click !

When the window is not maximized the qwt rubber band performance is ok. When I maximize it then i get all the laggy behavior. I did not change the size of the QRubberBand similarly to the qwt one so after maximising the window of the example start the mouse selection from the higher upper left corner and move the mouse around.

Thanks for your help,
Xerion

PS. For some reason the .h file is renamed automatically so please rename it according to the .cpp

Uwe
28th April 2011, 22:13
QwtPicker::drawRubberband is not only used for drawing the rubberband, but also for creating the mask of the rubberband ( a QBitmap ). Therefore it is not allowed to manipulate the assigned pen/brush like you did it.

Instead assign your fill color to the rubberband pen (QwtPicker::setRubberBandPen) and add the following code somewhere in your drawRubberband method:


painter->setBrush( painter->pen().color() );
if ( painter->pen().color() != Qt::color1 )
painter->setOpacity(0.8);


HTH,
Uwe

xerionn
29th April 2011, 02:53
Uwe first of all thanks for your help, It definitely helps !

I wont say that I was not expecting that hehe, something was not looking good!
However I have to say that even like that the performance of what you propose is still incomparable to the usual QRubberBand. With smooth movement of the mouse its still bit laggy compared to violent and fast movements of the mouse and the QRubberBand is keeping up.

Additionally, using this I can not set a different QBrush color for the painter but I can only change the opacity.
This is not overly impoartant as i am kind of OK with not having different colors but I just wanted to get the usual rubberband colors which seems to be


// Pen
QColor highlight = this->plot->canvas()->palette().color(QPalette::Active, QPalette::Highlight);

// Brush
QColor dimHighlight = QColor(qMin(highlight.red()/2 + 110, 255), qMin(highlight.green()/2 + 110, 255), qMin(highlight.blue()/2 + 110, 255));



Thanks for your help again, its really appreciated !
Xerion

Uwe
29th April 2011, 08:01
However I have to say that even like that the performance of what you propose is still incomparable to the usual QRubberBand.
Don't compare apples with eggs: drawing an unfilled rectangle is something completely different than drawing a semitransparent filled rectangle. I'm pretty sure, that an usual unfilled Qwt rubberband will work even faster than a QRubberband ( a widget overlay with a non solid pen is also a performance killer ).

Nevertheless on my slow Atom box ( Linux with X11 or raster ) the code I have posted works fast enough to follow even hectic mouse movements in the friedberg example. So there should be something wrong in your code or there is something different in the environment of your application - or the power of your system is far behind mine.


Additionally, using this I can not set a different QBrush color for the painter but I can only change the opacity.
The only important thing is, that you fill everything with Qt::color1 in the situation, where the mask is painted. When drawing to the widget you can paint with whatever pen/brush you want.

Checking the pen color for Qt::color1 is one possibility to identify this, but of course there are others. f.e:


If ( painter->device()->depth() == 1 )
{
// this is the bitmap mask
}
else
{
// this is the rubberband widget
}

Uwe

xerionn
29th April 2011, 09:36
Don't compare apples with eggs: drawing an unfilled rectangle is something completely different than drawing a semitransparent filled rectangle. I'm pretty sure, that an usual unfilled Qwt rubberband will work even faster than a QRubberband ( a widget overlay with a non solid pen is also a performance killer ).


Agree on all the above . However i should mention that i dont see any performance difference wuth a QRubberband with all the transparencies.


Nevertheless on my slow Atom box ( Linux with X11 or raster ) the code I have posted works fast enough to follow even hectic mouse movements in the friedberg example. So there should be something wrong in your code or there is something different in the environment of your application - or the power of your system is far behind mine.


Its fine when the window does not have a big size, no issues there ! . However in my 21 inch screen, when I maximise the friedberg for example, the rubberband cannot follow my movements as mentionned.


The only important thing is, that you fill everything with Qt::color1 in the situation, where the mask is painted. When drawing to the widget you can paint with whatever pen/brush you want.


I have tested of course setting in my drawRubberBand function the pen and the brush without any additional checks:

painter->setBrush( dimHighlight);
painter->setPen(highlight);
However, whenever I do that I only get a "normal qwt" rectangle without any fill color. When the colors of brush and pen are same only then i get the rectangle to be filled !

Thanks for the help Uwe. I am still confused with the result.. If everything is fine on your Atom processor I should not be having any issues but to the contrary I do (only when maximised!)... I will do some more testing and then see what I will implement !


Thanks,

Xerionn