Swing框架之Model之一

     构建应用程序应该以数据为中心,而不是以用户界面为中心,这是一个良好的编程习惯。为支持这种编程范式,Swing为每种带有逻辑数据或值的组件定义了独立的模型接口,这种分割使程序可以选择向Swing组件中嵌入自己的模型实现。

       下面表格列出Swing中组件及其模型的映射关系:

组件Model接口Model类型
JButtonButtonModelGUI状态
JToggleButtonButtonModelGUI状态/应用数据
JCheckBoxButtonModelGUI状态/应用数据
JRadioButtonButtonModelGUI状态/应用数据
JMenuButtonModelGUI状态
JMenuItemButtonModelGUI状态
JCheckBoxMenuItemButtonModelGUI状态/应用数据
JRadioButtonMenuItemButtonModelGUI状态/应用数据
JComboBoxComboBoxModel应用数据
JProgressBarBoundedRangeModelGUI状态/应用数据
JScrollBarBoundedRangeModelGUI状态/应用数据
JSliderBoundedRangeModelGUI状态/应用数据
JTabbedPaneSingleSelectionModelGUI状态
JListListModel应用数据
JListListSelectionModelGUI状态
JTableTableModel应用数据
JTableTableColumnModelGUI状态
JTreeTreeModel应用数据
JTreeTreeSelectionModelGUI状态
JEditorPaneDocument应用数据
JTextPaneDocument应用数据
JTextAreaDocument应用数据
JTextFieldDocument应用数据
JPasswordFieldDocument应用数据

Swing模型分类

       Swing提供的模型分为两大类:GUI状态模型和应用数据模型。

       GUI状态模型是描述GUI控件可视化状态的接口,如按钮是否按下,或列表中那一项被选中。GUI状态模型通常仅在图形用户界面(GUI)环境中用到。通常来说,虽然编写使用GUI状态模型分离程序,尤其是当多个GUI控件共享状态,或当操作一个控件自动更新另一个的值时比较有用,但GUI状态模型在Swing中并不是必需的,完全可以通过组件顶层方法操作GUI控件的状态,而不必和模型直接交互。

       应用数据模型是描述具有应用程序含义数据的接口,比如表格中的数据,或列表显示的选项。这些数据模型为Swing提供了一个清晰分割应用程序界面和数据逻辑的强大编程模式。对于以数据为核心的Swing组件,比如JTree和JTable,强烈推荐使用数据模型进行交互。

       当然一些组件的模型根据应用场景的不同其分类介于GUI状态模型和应用数据模型之间,比如JSlider和JProgressBar 的BoundedRangeModel。

       Swing的可分离模型接口并没有明确界定GUI状态模型和应用数据模型。这儿所以做此说明,目的是让你更好的理解何时以及为何要需要使用分离的模型。

共享模型定义

       值得注意的是,上文中表格中,许多组件的数据抽象相似,只需一个接口而不用过分泛化时,组件可以共享同一模型定义。共享模型定义允许在不同组件之间自动连接。比如,JSlider和JScrollBar都使用BoundedRangeModel接口,因此可以在一个JScrollBar和一个JSlider之间共享同一个BoundedRangeModel实例,这样它们之间的状态就总是同步的。

http://static4.photo.sina.com.cn/orignal/4b6047bce026f4d111d73

分离模型编程接口

       使用模型的Swing组件必须提供访问修改模型的set/get方法,即模型必须是该组件的限定性属性。比如,JSlider使用BoundedRangeModel接口作为它的模型定义,因此它必须提供下面方法:

   public BoundedRangeModel getModel()
   publicvoidsetModel(BoundedRangeModelmodel)

      所有Swing组件有一个共同点:如果你不设置它的模型,组件会在内部创建/安装一个缺省模型。这些缺省模型类的命名习惯是在接口名称之前加上“Default”,比如JSlider的构造函数中初始化一个DefaultBoundedModel对象。

public JSlider(int orientation, int min, int max, intvalue){
  checkOrientation(orientation);
   this.orientation = orientation;
   this.model = newDefaultBoundedRangeModel(value, 0, min, max);
   this.model.addChangeListener(changeListener);
  updateUI();
}

       如果程序接着调用setModel(),缺省的模型就被替换了,比如下面例子:

JSlider slider = new JSlider();
BoundedRangeModel myModel = new DefaultBoundedRangeModel() {
      public void setValue(int n){
         System.out.println("SetValue: "+ n);
         super.setValue(n);
      }
   });
slider.setModel(myModel);

       对于更复杂的模型(如JTable和JList),Swing还提供一个抽象模型实现,让开发者不需要从头开始创建自己的模型。

       如JList的模型接口是ListModel,Swing同时提供了DefaultListModel和AbstractListModel两个类来协助开发者创建自定义的列表模型。

模型改变通知

       当数据或者发生变动时,模型必须通知所有相关方(比如视图)。Swing模型使用前面文章所讲述的事件模型来实现这种触发。Swing中有两种方法发送这种通知:

       发送轻量级通知,表明状态已经改变,需要Listener通过查询模型,发现什么改变了并做出响应。此方法的优点是单独事件实例能用作该模型的所有通知,同时对于需要频繁通知的事件非常有用(比如JScrollBar被拖动时)。

       发送状态化通知,详细描述模型如何改变。这种方法需要为每个通知创建一个新的事件实例。当通知通过查询模型不能有效地给Listener提供足够的信息时,此方法非常有用。比如当JTable的一列表格数据发生改变时。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值