nbsp; timer = new Timer(); timer.schedule(new SecondsTask(this),1000,1000); }
running = !running; }
/** * The task that counts the seconds. */ private class SecondsTask extends TimerTask {
/** * We're not interested in the implementation so I omit it. */
} }
Controller只定义了用户可以执行的并且能够从下列接口抽象出来的actions。
public interface TimeController {
/** * Action invoked when the user wants to start/stop the timer */ void userStartStopTimer();
/** * Action invoked when the user wants to restart the timer */ void userRestartTimer();
/** * Action invoked when the user wants to modify the timer period * * @param newPeriod the new period */ void userModifyPeriod(Integer newPeriod); }
你可以使用你自己喜欢的GUI编辑器来画这个view。出于我们自身的情况,我们只需要几个公共的methods就可以提供足够的功能来更新view的fields,如下面的这个例子所示:
/** * Updates the GUI seconds fields */ public void setScnFld(Integer sec){ // scnFld is a Swing text field SwingUtilities.invokeLater(new Runnable() { public void run() { scnFld.setText(sec.toString()); } }); }
在这里我们注意到我们正在使用POJOs (plain-old Java objects),同时我们不用遵守任何编码习惯或者实现特定的接口(事件激发代码除外)。剩下的就只有定义组件之间的绑定了。
事件分派annotations
绑定机制的核心就是@ModelDependent annotation的定义:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ModelDependent {
String modelKey() default "";
String propertyKey() default "";
boolean runtimeModel() default false;
boolean runtimeProperty() default false;
}
这个annotation能被用在view的methods上,同时dispatcher也会使用这些提供的参数(即modelKey和propertyKey)来确定这个view将会响应的model事件。这个view既使用modelKey参数来指定它感兴趣的可利用的models又使用propertyKey参数来匹配分配的java.beans.PropertyChangeEvents的属性名称。
View method setScnFld()因此被标注以下信息(这里,timeModel提供了用来将model注册到dispatcher上的key):
/** * Updates the GUI seconds fields */ @ModelDependent(modelKey = "timeModel", propertyKey = "seconds") public void setScnFld(final Integer sec){ // scnFld is a Swing text field SwingUtilities.invokeLater(new Runnable() { &nb 上一页 [1] [2] [3] [4] [5] 下一页
|