Reputation: 86542
When writing GUIs, I've frequently come over the following problem: Assume you have a model and a controller. The controller has a widget W
that is used to show a property X
of the model.
Because the model might be changed from outside the controller (there might be other controllers using the same model, undo operations etc), the controller listens to changes on the model. The controller also listens to events on the widget W
and updates the property X
accordingly.
Now, the following happens:
W
is changedX
in the modelX
and sets it in the widgetThere are several possible solutions for that:
In the past, I usually went for option 1., because it's the simplest thing. It has the drawback of cluttering your classes with flags, but the other methods have their drawbacks, too.
Just for the record, I've had this problem with several GUI toolkits, including GTK+, Qt and SWT, so I think it's pretty toolkit-agnostic.
Any best practices? Or is the architecture I use simply wrong?
@Shy: That's a solution for some cases, but you still get a round of superfluous events if X
is changed from outside the controller (for instance, when using the command pattern for undo/redo), because then the value has changed, W
is updated and fires an event. In order to prevent another (useless) update to the model, the event generated by the widget has to be swallowed.
In other cases, the model might be more complex and a simple check on what exactly has changed might not be feasible, e.g. a complex tree view.
Upvotes: 17
Views: 299
Reputation: 1018
Usually you should respond to input events in the widget and not to change events. This prevents this type of loop from occuring.
Upvotes: 3
Reputation: 3342
Flags to indicate updaing work. You can wrap them in methods like BeginUpdate and EndUpdate.
Upvotes: 1
Reputation: 79003
The standard QT way of dealing with this and also the one suggested in their very useful tutorial is to make the change to the value in the controller only if the new value is different from the current value.
This is way signals have the semantics of valueChanged()
Upvotes: 5