新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论Java, J2SE, J2ME, J2EE, 以及Eclipse, NetBeans, JBuilder等Java开发环境,还有JSP, JavaServlet, JavaBean, EJB以及struts, hibernate, spring, webwork2, Java 3D, JOGL等相关技术。
    [返回] 中文XML论坛 - 专业的XML技术讨论区计算机技术与应用『 Java/Eclipse 』 → 通过Java Swing看透MVC设计模式[转帖] 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 2988 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 通过Java Swing看透MVC设计模式[转帖] 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     DMman 帅哥哟,离线,有人找我吗?魔羯座1984-1-11
      
      
      威望:1
      头衔:数据挖掘青年
      等级:研二(Pi-Calculus看得一头雾水)(版主)
      文章:803
      积分:5806
      门派:W3CHINA.ORG
      注册:2007/4/9

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给DMman发送一个短消息 把DMman加入好友 查看DMman的个人资料 搜索DMman在『 Java/Eclipse 』的所有贴子 点击这里发送电邮给DMman 访问DMman的主页 引用回复这个贴子 回复这个贴子 查看DMman的博客楼主
    发贴心情 通过Java Swing看透MVC设计模式[转帖]

    http://www.javathinker.org/main.jsp?bc=showessay.jsp&id=612

    一个好的用户界面(GUI)的设计通常可以在现实世界找到相应的表现。例如,如果在您的面前摆放着一个类似于电脑键盘按键的一个简单的按钮,然而就是这么简单的一个按钮,我们就可以看出一个GUI设计的规则.

    一个好的用户界面(GUI)的设计通常可以在现实世界找到相应的表现。例如,如果在您的面前摆放着一个类似于电脑键盘按键的一个简单的按钮,然而就是这么简单的一个按钮,我们就可以看出一个GUI设计的规则,它由两个主要的部分构成,一部分使得它具有了按钮应该具有的动作特性,例如可以被按下。另外一部分则负责它的表现,例如这个按钮是代表了A还是B。

      看清楚这两点你就发现了一个很强大的设计方法,这种方法鼓励重用reuse,而不是重新设计redesign。你发现按钮都有相同的机理,你只要在按钮的顶上喷上不同的字母便能制造出“不同”的按钮,而不用为了每个按钮而重新设计一份图纸。这大大减轻了设计工作的时间和难度。

      如果您把上述设计思想应用到软件开发领域,那么取得相似的效果一点都不让人惊奇。一个在软件开发领域应用的非常广泛的技术Model/View/Controller(MVC)便是这种思想的一个实现。

      这当然很不错,但是或许您又开始疑惑这和java基础类JFC(Java Foundation Class)中的用户界面设计部分(Swing)又有什么关系呢?好的,我来告诉你。

      尽管MVC设计模式通常是用来设计整个用户界面(GUI)的,JFC的设计者们却独创性的把这种设计模式用来设计Swing中的单个的组件(Component),例如表格Jtable,树Jtree,组合下拉列表框JcomboBox等等等等。这些组件都有一个Model,一个View,一个Controller,而且,这些model,view,controller可以独立的改变,就是当组件正在被使用的时候也是如此。这种特性使得开发GUI界面的工具包显得非常的灵活。

      MVC设计模式把一个软件组件区分为三个不同的部分,model,view,controller。

      Model是代表组件状态和低级行为的部分,它管理着自己的状态并且处理所有对状态的操作,model自己本身并不知道使用自己的view和controller是谁,系统维护着它和view之间的关系,当model发生了改变系统还负责通知相应的view。

      View代表了管理model所含有的数据的一个视觉上的呈现。一个Model可以有一个以上的View,但是Swing中却很少有这样的情况。

      Controller管理着model和用户之间的交互的控制。它提供了一些方法去处理当model的状态发生了变化时的情况。

      使用键盘上的按钮的例子来说明一下:Model就是按钮的整个机械装置,View/Controller就是按钮的表面部分。

      下面的图解释了如何把一个JFC开发的用户界面分为model,view,controller,注意,view/Controller被合并到了一起,这是MVC设计模式通常的用法,它们提供了组件的用户界面(UI)。

      用Button的例子详细说明

      为了更好的理解MVC设计模式和Swing用户界面组件之间的关系,让我们更加深入的进行分析。我将采用最常见的组件button来说明。

      我们从model来开始。

      Model

      一个按钮的model所应该具备的行为由一个接口ButtonModel来完成。一个按钮model实例封装了其内部的状态,并且定义了按钮的行为。它的所有方法可以分为四类:

      1、查询内部状态

      2、操作内部状态

      3、添加和删除事件监听器

      4、发生事件

    法。

      程序员通常并不会直接和model以及view/controller打交道,他们通常隐藏于那些继承自java.awt.Component的组件里面了,这些组件就像胶水一样把MVC三者合三为一。也正是由于这些继承的组件对象,一个程序员可以很方便的混合使用Swing组件和AWT组件,然后,我们知道,Swing组件有很多都是直接继承自相应的AWT组件,它能提供比AWT组件更加方便易用的功能,所以通常情况下,我们没有必要混合使用两者。

    一个实例

      现在我们已经明白了Java类与MVC各个部分的对应关系,我们可以更加深入一点去分析问题了。下面我们将要讲述一个小型的使用MVC模式开发的例子。因为JFC十分的复杂,我只能把我的例子局限于一个用户界面组件里面(如果你猜是一个按钮的例子,那么你对了!)

      让我们来看看这个例子的所有部分吧。

      Button类

      最显而易见的开始的地方就是代表了按钮组件本省的代码,因为这个类是大部分程序员会接触的。

      就像我前面提到的,按钮用户界面组件类实际上就是model和view/controller的之间的黏合剂。每个按钮组件都和一个model以及一个controller关联,model定义了按钮的行为,而view/controller定义了按钮的表现。而应用程序可以在任何事件改变这些关联。让我们看看得以实现此功能的代码。

    public void setModel(ButtonModel buttonmodel)
    {
     if (this.buttonmodel != null)
     {
      this.buttonmodel.removeChangeListener(buttonchangelistener);
      this.buttonmodel.removeActionListener(buttonactionlistener);

      buttonchangelistener = null;
      buttonactionlistener = null;
     }

     this.buttonmodel = buttonmodel;

     if (this.buttonmodel != null)
     {
      buttonchangelistener = new ButtonChangeListener();
      buttonactionlistener = new ButtonActionListener();

      this.buttonmodel.addChangeListener(buttonchangelistener);
      this.buttonmodel.addActionListener(buttonactionlistener);
     }

     updateButton();
    }

    public void setUI(ButtonUI buttonui)
    {
     if (this.buttonui != null)
     {
      this.buttonui.uninstallUI(this);
     }

     this.buttonui = buttonui;

     if (this.buttonui != null)
     {
      this.buttonui.installUI(this);
     }

     updateButton();
    }

    public void updateButton()
    {
     invalidate();
    }

      在进入下一节之前,你应该多花一些时间来仔细阅读一下Button类的源代码。

      ButtonModel类

      ButtonModel维护着三种类型的状态信息:是否被按下(pressed),是否“武装上了”(armed),是否被选择(selected)。它们都是boolean类型的值。

      一个按钮被按下(pressed)是指当鼠标在按钮上面的时候,按下鼠标但是还没有松开鼠标按钮的状态,及时用户此时把鼠标拖拽到按钮的外面也没有改变这种状态。

      一个按钮是否“武装了”(armed)是指按钮被按下,并且鼠标还在按钮的上面。

      一些按钮还可能被选择(selected),这种状态通过重复的点击按钮取得true或者false的值。

      下面的代码是状态pressed的一个缺省的实现。状态armed以及selected实现的代码与之类似。ButtonModel类应该被继承,这样可以覆盖缺省的状态定义,实现有个性的按钮。

    private boolean boolPressed = false;

    public boolean isPressed()
    {
     return boolPressed;
    }

    public void setPressed(boolean boolPressed)
    {
     this.boolPressed = boolPressed;
     fireChangeEvent(new ChangeEvent(button));
    }

      在进入下一节之前,你应该多花一些时间来仔细阅读一下ButtonModel类的源代码。

    ButtonUI类

      按钮的view/controller是负责构建表示层的。缺省情况下它仅仅是用背景色画一个矩形而已,他们的子类继承了他们并且覆盖了绘制的方法,使得按钮可以有许多不同的表现,例如MOTIF,Windows 95,Java样式等等。

    public void update(Button button, Graphics graphics)
    {
    }

    public void paint(Button button, Graphics graphics)
    {
     Dimension dimension = button.getSize();
     Color color = button.getBackground();
     graphics.setColor(color);
     graphics.fillRect(0, 0, dimension.width, dimension.height);
    }

      ButtonUI类并不自己处理AWT事件,他们会使用一个定制的事件监听器把低级的AWT事件翻译为高级的Button模型期望的语义事件。下面就是安装/卸载事件监听器的代码。

    private static ButtonUIListener buttonuilistener = null;

    public void installUI(Button button)
    {
     button.addMouseListener(buttonuilistener);
     button.addMouseMotionListener(buttonuilistener);
     button.addChangeListener(buttonuilistener);
    }

    public void uninstallUI(Button button)
    {
     button.removeMouseListener(buttonuilistener);
     button.removeMouseMotionListener(buttonuilistener);
     button.removeChangeListener(buttonuilistener);
    }

      View/Controller实际上就是一些方法。他们不维护任何自己的状态信息。因此,许多按钮的实例可以共享一个ButtonUI实例。ButtonUI是通过在方面的参数列表里面加上按钮的引用来区分各个不同的按钮。

      同样,希望你能多花一些时间来看看ButtonUI类,然后咱们进入下一节。

      ButtonUIListener类

      ButtonUIListener类可以帮助Button类去转变鼠标或者键盘的输入为对按钮模型的操作。这个监听器类实现了:MouseListener,MouseMotionListener,ChangeListener接口,并且处理一下事件:

    public void mouseDragged(MouseEvent mouseevent)
    {
     Button button = (Button)mouseevent.getSource();
     ButtonModel buttonmodel = button.getModel();

     if (buttonmodel.isPressed())
     {
      if (button.getUI().contains(button, mouseevent.getPoint()))
      {
       buttonmodel.setArmed(true);
      }
      else
      {
       buttonmodel.setArmed(false);
      }
     }
    }

    public void mousePressed(MouseEvent mouseevent)
    {
     Button button = (Button)mouseevent.getSource();
     ButtonModel buttonmodel = button.getModel();
     buttonmodel.setPressed(true);
     buttonmodel.setArmed(true);
    }

    public void mouseReleased(MouseEvent mouseevent)
    {
     Button button = (Button)mouseevent.getSource();
     ButtonModel buttonmodel = button.getModel();
     buttonmodel.setPressed(false);
     buttonmodel.setArmed(false);
    }

    public void stateChanged(ChangeEvent changeevent)
    {
     Button button = (Button)changeevent.getSource();
     button.repaint();
    }

      总结

      我希望你能按照上面讲述的方法去做。如果不能,那么所有的努力都将白费。这个例子以及Swing用户界面组件的好处在于你不用去花时间去弄明白他们底层是如何设计实现的就可以很方便的使用他们了。他们都提供了缺省的model以及view/controller,然后,当你自己做组件的时候,你会发现上面的思想的强大之处。


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    数据挖掘青年 http://blogger.org.cn/blog/blog.asp?name=DMman
    纪录片之家 (很多纪录片下载)http://www.jlpzj.com/?fromuid=137653

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/11/2 8:32:00
     
     GoogleAdSense魔羯座1984-1-11
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 Java/Eclipse 』的所有贴子 点击这里发送电邮给Google AdSense 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/29 11:17:43

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    2,082.031ms