如鹏网 大学生计算机学习社区

CowNew开源团队

http://www.cownew.com 邮件请联系 about521 at 163.com

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  363 随笔 :: 2 文章 :: 808 评论 :: 0 Trackbacks

 

与VCL、AWT等框架中的图形界面框架不同,Swing创造性的采用了MVC(Model View Controller) 模式。MVC 把控件(Component)划分成三个部分:模型( Model):管理这个模块中所用到的数据和值,如某个数据的最大值、最小值、当前值等数据;视图( View):管理如何将模型显示给用户;控制器(Controller) 决定如何处理用户和该模块交互时产生的事件,如用户单击一个按钮等。Sun 出于对视图和控制器之间的依赖关系的考虑, 在 Swing 设计中将 MVC体系简化为分离模型体系 ( Separable Model Architecture) , 将其中的控制器和视图结合成 UI 代理。

界面中的每个控件都包含三种特征:

它的状态:比如一个按钮的状态

它的外观:颜色、尺寸等

它的行为:对事件作出的反应

以一个按钮为例,它有可用、不可用状态,在不同的LookAndFeel中有不同的外观显示,在鼠标按下、鼠标右击等事件中有自己独特的响应方式。如果管理按钮状态、绘制按钮外观,响应时间等任务都由按钮负责的话就违背了面向对象设计中的“单一责任原则”。Swing开发人员采用MVC模式解决了此问题,将控件的LookAndFeel同一个对象关联到一起,同时将其内容保存到另一个对象中。控制器负责控制用户输入事件。比如鼠标单击、按键操作等,它会决定将这些事件转换成模型中的改变.还是视图中的改变。例如,假定用户在文本框中按下某个键,控制器就会调用模型的“插入字符”命令。随后,模型会通知视图更新来显示新的模型。视图不用关心什么时候进行文字改变,只要模型通知它更新它就会更新。这样控制器只用与用户交互并把交互结果反映到模型中去;模型负责维护状态,当状态变化时通知视图更新显示;视图不负责用户交互的状态维护,它只是根据模型中的状态绘制不同的界面。

Swing中的大多数控件的模型是由一个名字以Model结尾的接口实现的。比如按钮对应的模型接口就是 ButtonModel,JDK中定义了ButtonModel的默认实现类DefaultButtonModel。下面是ButtonModel各个方法的说明:

boolean isArmed():如果按钮被按下,且鼠标指针仍停留在按钮上则返回true

boolean isSelected():如果按钮处于选择状态则返回true

boolean isEnabled():如果按钮可用则返回true

boolean isPressed():如果按钮被按下,但鼠标没有松开,则返回true

boolean isRollover():如果鼠标指针在按钮之上则返回true

public int getMnemonic():返回按钮的助记键

public String getActionCommand():返回命令字符串

此外还有对应的设置状态方法:public void setArmed(boolean b)、public void setSelected(boolean b)、public void setEnabled(boolean b)、public void setPressed(boolean b)、public void setRollover(boolean b)、public void setMnemonic(int key)、public void setActionCommand(String s)等。

每一个JButton都保存着一个ButtonModel对象,我们可以通过JButton的getModel方法来取得该模型对象:

JButton btn = new JButton(“test”);

ButtonModel btnModel = btn.getModel();

通过这个模型对象我们就可以得到按钮的是否可用等状态,不过这个模型是给控件开发者使用的,对于普通使用者来说无需直接调用它,JButton提供了方法来间接的取得这些属性,这一点可以从AbstractButton类的isSelected方法中看出来:

public boolean isSelected()

{

return model.isSelected();

}

Swing中大部分控件都由自己的模型,比如JList控件的ListModel、JTable的TableModel、JSpinner的SpinnerModel、JComboBox的SpinnerModel(SpinnerModel是从ListModel派生出来的),这些模型也由默认的实现,名称通常为模型名前加Default。

Swing中的大多数控件的视图是由一个名字以UI结尾的类实现的,比如按钮对应的模型接口就是 ButtonUI。由于视图在不同的LookAndFeel中有不同的展现形式,所以控件的视图对每一种LookAndFeel都提供了不同的实现。以JLabel为例,它就有MetalLabelUI、MotifLabelUI、WindowsLabelUI等对应不同LookAndFeel的实现。所有的视图都要直接或者间接的从ComponentUI抽象类派生,ComponentUI类中的方法都是供Model回调使用的,下面是ComponentUI主要方法的说明:

public void installUI(JComponent c):这个方法在ComponentUI 实例被安装到UI代理的时候被触发,用来根据LookAndFeel配置控件。它需要完成如下工作:为Color、Font、Border、Icon等类型的属性设定默认值;根据需要设置布局管理器;创建子控件;初始化监听器;为控件设置PropertyChangeListener 监听器以检测控件属性变化事件;初始化快捷键、Tab键顺序等;初始化数据;

public void uninstallUI(JComponent c):这个方法在ComponentUI 实例被从UI代理移除的时候触发。需要在此方法中撤销任何在installUI中进行的配置,要保证JComponent实例变为洁净状态(也就是没有监听器,没有LookAndFeel专有属性等)。它需要完成如下工作:从控件中移除border;从控件中移除布局管理器;从控件中移除子控件;从控件中移除事件、属性监听器、从控件中移除快捷键、Tab键顺序等;将数据标记为可以垃圾回收。

public void paint(Graphics g, JComponent c):为本视图的LookAndFeel绘制控件。

public void update(Graphics g, JComponent c):通知UI代理绘制指定控件。当特定的控件被绘制的时候此方法会被触发。这个方法的默认实现是用背景色填充控件,并且立即调用paint方法。

public Dimension getPreferredSize(JComponent c):返回当前LookAndFeel下控件的最佳尺寸。默认实现是返回null;

public Dimension getMinimumSize(JComponent c):返回当前LookAndFeel下控件的最小尺寸。默认实现是返回getPreferredSize的值;

public Dimension getMaximumSize(JComponent c):返回当前LookAndFeel下控件的最大尺寸。默认实现是返回getPreferredSize的值;

public boolean contains(JComponent c, int x, int y):判断指定的x、y坐标是否存在于当前LookAndFeel下的控件中。

public static ComponentUI createUI(JComponent c):为指定的控件返回UI代理实例。如果UI代理子类是无状态的,它也可以返回多控件共享的实例。如果UI代理子类是有状态的,则它必须为某个控件返回一个新的实例。

public int getAccessibleChildrenCount(JComponent c):返回所有可访问子控件的数量。

public Accessible getAccessibleChild(JComponent c, int i):返回指定的子控件

posted on 2007-04-19 19:37 CowNew开源团队 阅读(3865) 评论(3)  编辑  收藏

评论

# re: Swing中的MVC 2007-04-19 22:00 匿名
骨的,正在学习swing,对我很有帮助  回复  更多评论
  

# re: Swing中的MVC 2007-04-20 09:00 BeanSoft
Swing 的思路设计的如此之好, 以至于好些 JS 组件库也用这种思路, 例如: YUI-Ext. 这种思路好处就是各层可以单独实现/修改, 加入换肤功能等, 坏处就是第一次来学曲线比较高. 其实比起来 RCP 也是有很高学习曲线的了, 不但要学 SWT/JFace, 还得看 Eclipse Plugin 开发, 画图的项目还得看 EMF 等.  回复  更多评论
  

# re: Swing中的MVC 2007-04-20 13:41 sqhe18
是啊,所以我觉得NetBeansRCP也是不错的,关键不需要我再去学习SWT/Jface 之类的,而且它的插件机制相对于Eclipse来的简单。  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: