2008-09-24 67 views
17

编写GUI时,我经常遇到以下问题:假设您有一个模型和一个控制器。控制器有一个小部件W,用于显示模型的属性X在GUI中突破事件周期

由于模型可能会从控制器外部更改(可能有其他控制器使用相同的模型,撤消操作等),因此控制器会侦听模型上的更改。控制器还监听小部件W上的事件并相应地更新属性X

现在,将出现以下情况:

  1. 产生一个事件在W的值改变,在控制器在调用处理程序
  2. 控制器设置新值对于X中的型号
  3. m Odel等发射事件,因为它已经被改变
  4. 控制器接收来自模型的变化事件
  5. 控制器得到的X值,并将其设置在微件
  6. 转到1.

有几种可能的解决方案为:

  1. 修改控制器以在模型更新时设置标志,并且如果设置此标志,则不响应来自模型的任何事件。
  2. 断开控制器暂时(或告诉模式不发送一段时间的任何事件)
  3. 从窗口小部件

在过去的冻结任何更新,我经常去的选项1,因为它是最简单的事情。它有用标志混乱你的类的缺点,但其他方法也有它们的缺点。为了记录,我已经遇到了包括GTK +,Qt和SWT在内的几个GUI工具包的问题,​​所以我认为它非常适用于工具包不可知论的问题。

任何最佳实践?或者我使用的架构完全错误?

@Shy:这是某些情况下的解决方案,但如果从控制器外部更改X(例如,使用命令模式进行撤销/重做时),仍会发生一轮多余的事件,已更改,W已更新并触发了一个事件。为了防止对模型进行另一次(无用的)更新,必须吞噬由Widget生成的事件。
在其他情况下,模型可能更加复杂,并且简单地检查确切的改变可能是不可行的,例如,一个复杂的树视图。

+0

我在MFC中一直有列表框出现此问题。 – 2008-09-24 00:34:58

回答

3

通常您应该对小部件中的输入事件做出响应,而不是更改事件。这可以防止发生这种类型的循环。

  1. 用户改变输入在微件
  2. 的widget发出变化事件(滚动完成/输入点击/鼠标离开等)
  3. 控制器响应,转换在模型中改变
  4. 模型发出事件
  5. 控制器响应,在插件改变值
  6. 值改变事件发射的,而不是由控制器听取
5

处理这个问题的标准QT方式以及在他们非常有用的教程中提出的方法是,只有当新值与当前值不同时,才能更改控制器中的值。
这路信号有valueChanged()

see this tutorial

1

标志的语义来表示updaing工作。您可以将它们封装在BeginUpdate和EndUpdate等方法中。

+0

这是一种常见的做法,还是你只是在做一个有根据的猜测? – Statement 2008-09-24 01:12:28

+0

我已经使用标志来指示MFC Windows开发中的更新状态,它具有带有多个View架构的Document。最近在.Net Windows开发中,我使用了标志来指示在init中是否触发了选择更改事件,并且可以忽略它。 – Leah 2008-09-24 04:45:35