PDA

View Full Version : How can I avoid the paintEvent after resizing a widget?



jianliang79
9th September 2009, 06:25
I am writing a custom widget using Qt 4.5 and I am looking for
some way to optimze its refresh.
by default Qt will invalidate all the area occupied by the widget
after it has been resized, but this is not what I want. And I know
there is a attribute called Qt::WA_StaticContents to let the widget
just receive paint events only for parts of itself that are newly
visible, but this dosen't applicable to my widget. my widget must
refresh all the area after a vertical resizing but only need to
refresh the newly visible part after a horizontal resizing. So I can
use this attribute, I have to handle this in sizeEvent manually. but
How can I avoid the paintEvent triggered by Qt after resizing a
widget?
Thanks

yogeshgokul
9th September 2009, 07:20
Ignore it if you don't like flag solutions. ;)

Simply set a flag in resize event.
Check that flag in paint event, If the flag is set then ignore/accept/propagate the paintevent.
Only you will be responsible for the aftereffects of innoring the repainting after resize event. :cool:

jianliang79
9th September 2009, 08:48
Thanks for your reply. I think the solutions from you will work.
But I have another solution: I set the attribute Qt::WA_StaticContents to my widget and check the new size and old size of the widget in resize event, if it has been vertically resized I will update(just update, not repaint) the whole area of my widget in resize event handler, but if it hasn't I'll do nothing in resize event handler. Do you think this is a feasible solution?

yogeshgokul
9th September 2009, 08:54
Go for it.

wysota
9th September 2009, 09:31
if it has been vertically resized I will update(just update, not repaint) the whole area of my widget in resize event handler

What's the difference between "just update" and "repaint".

jianliang79
9th September 2009, 14:47
What's the difference between "just update" and "repaint".
update means I just invalidate a region of the widget by calling QWidget::update(), I will receive a repaint event in the next iteration of the event loop, and multiple update will likely be merged in a single update and we only receive one repaint event for these updates.
repaint means calling QWidget::repaint() which will call paintEvent() immediately to do the render job.

wysota
9th September 2009, 17:35
Ok, but how does it differ in your case? Qt calls update() upon resize as well...

jianliang79
10th September 2009, 02:58
Ok, but how does it differ in your case? Qt calls update() upon resize as well...

yes, It differ in my case at least when I create my widget as a top level widget. look at the following code(from qapplication_win.cpp) :


QResizeEvent e(newSize, oldSize);
QApplication::sendSpontaneousEvent(this, &e);
if (d_func()->paintOnScreen()) {
QRegion updateRegion(rect());
if (testAttribute(Qt::WA_StaticContents))
updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height());
d_func()->syncBackingStore(updateRegion);
} else {
d_func()->syncBackingStore();
}


Qt will just send resizeEvent to my widget and I don't see any of the event handler will call update(). In fact it is done in d_func()->syncBackingStore(); this function will sync the backing store of the top level widget, in my case, it will draw the newly exposed area of the widget immediately(in syncBackingStore() Qt will always deem the newly exposed area as dirty even I have called repaint() in my resizeEvent handler). So if I call repaint() in my resizeEvent handler, the newly exposed area will be redrawn twice.

wysota
10th September 2009, 08:57
But why do you want to call repaint() or update() in your resizeEvent at all? It is obvious that a paint event will follow it if necessary. Maybe if you could express what is the purpose of all those manipulations we could suggest a cleaner approach?

jianliang79
10th September 2009, 11:03
But why do you want to call repaint() or update() in your resizeEvent at all? It is obvious that a paint event will follow it if necessary. Maybe if you could express what is the purpose of all those manipulations we could suggest a cleaner approach?

Sorry, maybe I don't express my question clearly enough, now I will describe it again:
As I have mentioned in my first post: I am writing a widget, this widget must refresh all the area after a vertical resizing but only need to refresh the newly visible part after a horizontal resizing( a ruler widget may have the same behaviour).
1) If I don't set Qt::WA_StaticContents attribute to my widget, Qt will notify me to redraw the entire area of the widget after any kind of resizing. But in the case of horizontal resizing it will waste a lot time to redraw the unchanged part of my widget. I think this is not an effient way.
2) If I set Qt::WA_StaticContents attribute to my widget, Qt will only notify me to redraw the newly exposed part of my widget after resizing, but in the case of vertical resizing this will make me unable to redraw the entire widget.
It seems that I have to manually control which part of my widget need to be redrawn in resize event handler by comparing the old size and new size of my widget. I am interested in that is there an elegent way to let me control that by myself?
Thanks.

wysota
10th September 2009, 13:04
It might prove much easier to cache the looks of your widget and simply rerender the already computed part instead of trying to work around architectures.

jianliang79
11th September 2009, 02:26
It might prove much easier to cache the looks of your widget and simply rerender the already computed part instead of trying to work around architectures.

Thanks. I will keep that in mind.