Swing


天行健 君子以自强不息

posts - 69, comments - 215, trackbacks - 0, articles - 16
   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

Swing框架之Model

Posted on 2007-10-12 16:16 zht 阅读(806) 评论(0)  编辑  收藏 所属分类: Swing
   构建应用程序应该以数据为中心,而不是以用户界面为中心,这是一个良好的编程习惯。为支持这种编程范式,Swing为每种带有逻辑数据或值的组件定义了独立的模型接口,这种分割使程序可以选择向Swing组件中嵌入自己的模型实现。

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

组件 Model接口 Model类型
JButton ButtonModel GUI状态
JToggleButton ButtonModel GUI状态/应用数据
JCheckBox ButtonModel GUI状态/应用数据
JRadioButton ButtonModel GUI状态/应用数据
JMenu ButtonModel GUI状态
JMenuItem ButtonModel GUI状态
JCheckBoxMenuItem ButtonModel GUI状态/应用数据
JRadioButtonMenuItem ButtonModel GUI状态/应用数据
JComboBox ComboBoxModel 应用数据
JProgressBar BoundedRangeModel GUI状态/应用数据
JScrollBar BoundedRangeModel GUI状态/应用数据
JSlider BoundedRangeModel GUI状态/应用数据
JTabbedPane SingleSelectionModel GUI状态
JList ListModel 应用数据
JList ListSelectionModel GUI状态
JTable TableModel 应用数据
JTable TableColumnModel GUI状态
JTree TreeModel 应用数据
JTree TreeSelectionModel GUI状态
JEditorPane Document 应用数据
JTextPane Document 应用数据
JTextArea Document 应用数据
JTextField Document 应用数据
JPasswordField Document 应用数据

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实例,这样它们之间的状态就总是同步的。


分离模型编程接口

       使用模型的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的一列表格数据发生改变时。