QWidget paint event "chain reaction" - how to implement without recursion?
-
Intro:
I am writing an app which displays a list of custom QWidgets (namely, "ScopeWidget") in a container widget with VBoxlayout ("ScopeView").
Every scopeWidget has a pointer to an own data source class ("Scope"). These objects are logically arranged in groups, i.e. there are some shared parameters ("ScopeShared") among objects in one group.
These parameters are needed when retrieving (or preparing) the data which has to be displayed on a scopeWidget.
One step further:
A scopeWidget needs two sets of parameters: these given by "Scope" and given by "ScopeGroup".
A scopeWidget can, by user action, change some of the shared parameters in a group, thus invalidating all previous retrieved data, held by "Scope"s in this group.
By default, there is no displayable data in a "Scope". Data is retrieved on demand - when a paintEvent occurs (this is the source of the problem). To get displayable data in a "Scope", one have to process all "Scopes" in this particular group (which yields usable data for all "Scope"s in the group).
How it works:
The user forces one of the scopeWidgets to change shared data in a group. After making these changes, all data held by "Scope"s in this group, is invalidated, so the change event reprocesses the whole group. And calls update() for all scopeWidgets in this group. Widgets are redrawn. This works...
The problem:
...is a paintEvent which occured spontanously. When the user changes something - I_know that this happened and I can process the scopeGroup prior to enqueuing updates of widgets. But when "something else" (the system itself) executes a paint event, I_need to process the whole group before any painting happens.
So the paint event does no painting directly, but executes scopeGroup processing, and after that, it paints the widget which had the painting event, and calls update() for all other widgets in that group - which in turn causes new paint events, which cause a next scopeGroup processing, one paint(), and update()'s for other widgets, which causes new paint events - it ends up as recursive repaint (and scopeGroup processing)
Lame solution:
flags - spontaneous paint events do group processing, one paint() for the requesting widget, and update()'s on the rest of widgets in the group, together with setting flags for every widget.This pseudocode depicts this mechanism:
@
paintEvent(QWidget *w)
{
if(w->flag)
{
w->paint(); w->flag=0;
}
else
{
w->group()->process();
w->paint();
QWidget *x;
foreach(x,group) if(x!=w) { x->flag=1; x->update(); }
}
@What would be IMHO better:
a) if widgets could be painted without a prior paint event (or call to update() or repaint() )... this would be the best ;], but it doesnt work in the straightforward and obvious way - is there any other way? - or
b) force the system to call a custom function instead the paint eventAre these 'better' solutions possible?
[edit: code tags added, koahnig]
-
welcome to devnet
You might want to check out the forum help for "code wrappings":http://qt-project.org/wiki/ForumHelp#e3f82045ad0f480d3fb9e0ac2d58fb01 They are helping to make your post's coding section easier to read.
-
Hi,
If I understood you right, you have some common configuration shared by a group of widget and custom configuration specific per widget. What is not really clear is: do your scopes use the same input data ?
Did you consider the Model View architecture ? This design would allow you to have the changes propagated "automatically". The model would tell the scopes connected to it that something has changed and they would update themselves.
Hope it helps
-
Changes made by the user are not of any concern, because I know exactly when changes occured, and can process these changes prior to painting, without calling processing functions from inside the paint event handler. The same rule applies to a timer based 'refresh' - first detecting changes, then processing, and finally painting.
But the problem is when the paint event handler is called spontaneously, by the system, e.g. when resizing or focusing the window. The paint event is called without previous processing, so there is no valid data for painting, and the software has to call the processing function from inside the paint event. And this is bad.
Scopes can, but don't have to, use the same input data. The user decides, which data is displayed on a scope. Scopes have access to a common, time stamp based data source, and can retrieve any value from any sample point.
-
It still sounds like the Model/View architecture would be good but anyway. If the problem is only when no data are available, why not simply have a test for data validity and then paint an empty scope when they are not ?