什么是MVC框架?
MVC(Model-View-Controller)框架,意为”模式-视图-控制器”。MVC应用程序总是由这三个部分组成的。与VCL、AWT等框架中的图形界面框架不同,Swing创造性的采用了MVC模式。
MVC把控件(Component)划分成三部分:
a)模式:管理这个模块中所用到的数据和值,如某个数据的最大值、最小值、当前值等数据;
b)视图:管理如何将模型显示给用户;
c)控制器:决定如何处理用户和该模块交互时产生的事件,如用户单击一个按钮等。
出于对视图和控制器之间的依赖关系的考虑,在Swing设计中将MVC体系简化为分离模型体系(Separable Model Architecture),将其中的控制器和视图结合成UI代理。
界面中的每个控件都包含以下3种特征:
a)状态:比如一个按钮的状态;
b)外观:颜色、尺寸等;
c)行为:对事件作出的反应。
举一个例子——按钮,它有可用和不可用这两种状态,在不同的Look And Feel中有不同的外观显示。在鼠标按下、鼠标右击等事件中,有自己独特的响应方式。如果管理按钮状态、绘制按钮外观,响应时间等任务都由按钮负责,则违背了面向对象设计中的“单一责任原则”。Swing开发人员采用MVC模式解决了此问题,将控件的Look And Feel同一个对象关联在一起,同时将其内容保存到另一个对象中。控制器负责控制用户输入事件。比如鼠标单击、按键操作等,它会决定将这些事件转换成模型中的改变,还是视图中的改变。例如,假定用户在文本框中按下某个键,控制器就会调用模型的“插入字符”命令。随后,模型会通知视图更新来显示新的模型。视图不用关心什么时候进行文字改变,只要模型通知它更新它就会更新。这样控制器只用于用户交互并把交互结果反映到模型中去;模型负责维护状态,当状态变化时通知视图更新显示;视图不负责用户交互的状态维护,它只是根据模型中的状态绘制不同的界面。
在Swing中,大多数控件的模型是由一个名字以Model结尾的接口实现的。比如,按钮对应的模型接口是Button Model,JDk中定义了Button Model的默认实现类Default Button Model。以下是Button Model各个方法的说明:
booleanisArmed():如果按钮被按下,且鼠标指针仍停留在按钮上则返回true;
booleanisSelected():如果按钮处于选择状态则返回true;
booleanisEnabled():如果按钮可用则返回true;
booleanisPressed():如果按钮被按下,但鼠标没有松开,则返回true;
booleanisRollover():如果鼠标指针在按钮之上则返回true;
publicintgetMnemonic():返回按钮的助记键;
publicStringgetActionCommand():返回命令字符串。
除此之外,还有对应的设置状态方法:public void set Armed(booleanb)、public void set Selected(booleanb)、public void set Enabled(booleanb)、public void set Pressed(booleanb)、public void set Rollover(booleanb)、public void set Mnemonic(intkey)、public void set Action Command(Strings)等。
每一个JButton都保存着一个Button Model对象,我们可以通过JButton的get Model方法来取得该模型对象:
JButtonbtn=newJButton(“test”);
Button Modelbtn Model=btn.getModel();
通过这个模型对象就可以得到按钮的是否可用等状态,但这个模型是给控件开发者使用的,对于普通使用者来说不用直接调用它,JButton提供了方法来间接地取得这些属性,这一点可以从Abstract Button类的is Selected方法中看出来:
publicbooleanisSelected()
{
returnmodel.isSelected();
}
Swing中大部分控件都有自己的模型,比如JList控件的List Model、J Table的Table Model、jsp inner的Spinner Model、JCombo Box的Spinner Model(Spinner Model是从List Model派生出来的),这些模型也由默认的实现,名称通常为模型名前加Default。
Swing中的大多数控件的视图是由一个名字以UI结尾的类实现的,比如按钮对应的模型接口就是Button UI。由于视图在不同的Look And Feel中有不同的展现形式,所以控件的视图对每一种LookAndFeel都提供了不同的实现。以JLabel为例,它就有Metal Label UI、Motif Label UI、Windows Label UI等对应不同Look And Feel的实现。
所有的视图都要直接或者间接的从Component UI抽象类派生,Component UI类中的方法都是供Model回调使用的,以下说明一下Component UI的主要方法:
#p#分页标题#e#
public void install UI(JComponentc):这个方法在Component UI实例被安装到UI代理的时候被触发,用来根据Look And Feel配置控件。它需要完成如下工作:为Color、Font、Border、Icon等类型的属性设定默认值;根据需要设置布局管理器;创建子控件;初始化监听器;为控件设置Property Change Listener监听器以检测控件属性变化事件;初始化快捷键、Tab键顺序等;初始化数据。
public void uninstall UI(JComponentc):这个方法在Component UI实例被从UI代理移除时触发。需要在此方法中撤销任何在install UI中进行的配置,要保证JComponent实例变为洁净状态(即没有监听器,没有Look And Feel专有属性等)。它需要完成如下工作:从控件中移除border;从控件中移除布局管理器;从控件中移除子控件;从控件中移除事件、属性监听器、从控件中移除快捷键、Tab键顺序等;将数据标记为可以垃圾回收。
public void paint(Graphicsg,JComponentc):为本视图的Look And Feel绘制控件。
public void update(Graphicsg,JComponentc):通知UI代理绘制指定控件。当特定的控件被绘制的时候此方法会被触发。这个方法的默认实现是用背景色填充控件,并且立即调用paint方法。
public Dimensionget Preferred Size(JComponentc):返回当前Look And Feel下控件的最佳尺寸。默认实现是返回null。
public Dimensionget Minimum Size(JComponentc):返回当前Look And Feel下控件的最小尺寸。默认实现是返回get Preferred Size的值。
public Dimensionget Maximum Size(JComponentc):返回当前Look And Feel下控件的最大尺寸。默认实现是返回get Preferred Size的值。
public boolean contains(JComponentc,intx,inty):判断指定的x、y坐标是否存在于当前Look And Feel下的控件中。
publicstatic Component UI create UI(JComponentc):为指定的控件返回UI代理实例。如果UI代理子类是无状态的,它也可以返回多控件共享的实例。如果UI代理子类是有状态的,则它必须为某个控件返回一个新的实例。
publicint get Accessible Children Count(JComponentc):返回所有可访问子控件的数量。
public Accessible get Accessible Child(JComponentc,inti):返回指定的子控件。
MVC框架还有很多优点,例如具有低耦合性、高重用性和可适用性、较低的生命周期成本、快速部署、可维护性、有利于软件工程化管理等等。