在编写 GUI 时,我经常遇到以下问题:假设您有一个模型和一个控制器。控制器有一个小部件W
,用于显示X
模型的属性。
因为模型可能会从控制器外部更改(可能有其他控制器使用相同的模型、撤消操作等),所以控制器会监听模型的更改。控制器还监听小部件上的事件W
并相应地更新属性X
。
现在,会发生以下情况:
- 中的值
W
已更改 - 生成事件,调用控制器中的处理程序
- 控制器
X
在模型中设置新值 - 模型发出事件,因为它已被更改
- 控制器从模型接收更改事件
- 控制器获取的值
X
并将其设置在小部件中 - 转到 1。
有几种可能的解决方案:
- 修改控制器以在模型更新时设置一个标志,如果设置了此标志,则不对来自模型的任何事件做出反应。
- 暂时断开控制器(或告诉模型一段时间不要发送任何事件)
- 冻结小部件中的任何更新
过去,我通常选择选项 1,因为这是最简单的事情。它的缺点是用标志使你的类变得混乱,但其他方法也有它们的缺点。
只是为了记录,我在几个 GUI 工具包中遇到了这个问题,包括 GTK+、Qt 和 SWT,所以我认为它与工具包无关。
有什么最佳实践吗?还是我使用的架构完全错误?
X
@Shy:这是某些情况下的解决方案,但是如果从控制器外部更改(例如,使用命令模式进行撤消/重做时),您仍然会得到一轮多余的事件,因为值已经改变,W
被更新并触发一个事件。为了防止对模型进行另一次(无用的)更新,必须吞下小部件生成的事件。
在其他情况下,模型可能更复杂,简单检查究竟发生了什么变化可能不可行,例如复杂的树视图。