您的位置: 文章阅读 ┆ 回首页
 
站内资源搜索:
┆ 将本文寄给朋友  

Swing框架之Model之二

 

作者:WilliamChen

 

 

轻量级通知

       下面Swing中的模型使用轻量级通知,它们是基于 ChangeListener、ChangeEvent接口的:

Model Listener Event
BoundedRangeModel ChangeListener ChangeEvent
ButtonModel ChangeListener ChangeEvent
SingleSelectionModel ChangeListener ChangeEvent


      ChangeListener接口只有一个通用方法:

public void stateChanged(ChangeEvent e)

      ChangeEvent中仅有的状态是事件源,因为所有通知中的事件源都是相同的,单独一个事件实例可以用作所有来自该模型的通知。使用此机制的模型支持下面的方法来添加和删除ChangeListeners:

   public void addChangeListener(ChangeListenerl)
   public voidremoveChangeListener(ChangeListenerl)

        获知JSlider数据发生变化的代码可以使用如下代码实现:

JSlider slider = new JSlider();
BoundedRangeModelmodel =slider.getModel();           
model.addChangeListener(new ChangeListener() {
      public voidstateChanged(ChangeEvent e) {
            // need to query themodel
            // to getupdatedvalue...
            BoundedRangeModel m=(BoundedRangeModel)e.getSource();
            System.out.println("model changed: "+
            m.getValue());
      }
});

       为给不想和分离式模型交互的程序提供方便,一些Swing组件类提供了直接在组件上注册ChangeListener的方法(组件可在组件内部侦听模型的数据变化,并将事件传播给任何注册在组件上的Listener),这些通知的唯一区别是,使用模型注册方式的事件源是该模型实例,而使用组件注册方式的事件源是该组件。

        因此我们可以将前面的例子简化成:

JSlider slider = newJSlider();
slider.addChangeListener(new ChangeListener() {
     public void stateChanged(ChangeEvent e) {
           //the source will be
           // the slider this time..
           JSlider s=(JSlider)e.getSource();
           System.out.println("valuechanged: "+s.getValue());
     }
});

状态化通知

       支持状态化通知的模型根据它们的目的提供不同的Listener接口和事件对象。下表是这些模型接口和事件对象的类:

Model Listener Event
ListModel ListDataListener ListDataEvent
ListSelectionModel ListSelectionListener ListSelectionEvent
ComboBoxModel ListDataListener ListDataEvent
TreeModel TreeModelListener TreeModelEvent
TreeSelectionModel TreeSelectionListener TreeSelectionEvent
TableModel TableModelListener TableModelEvent
TableColumnModel TableColumnModelListener TableColumnModelEvent
Document DocumentListener DocumentEvent
Document UndoableEditListener UndoableEditEvent

       Listener除了可以直接查询事件对象来跟踪内容改变外,这些API的作用与轻量级通知相似。比如下面的代码动态的跟踪JList被选中的项:

Stringitems[] = {"One", "Two", "Three");
JList list = new JList(items);
ListSelectionModel sModel =list.getSelectionModel();
sModel.addListSelectionListener(new ListSelectionListener() {
       publicvoidvalueChanged(ListSelectionEvent e) {
             // get change information directly
             // fromtheevent instance...
             if (!e.getValueIsAdjusting()) {
                  System.out.println("selection changed: " +
                  e.getFirstIndex());
             }
       }
});


自动视图更新

        模型没有任何表现它视图的固有知识,相反模型只有关心其状态改变的Listener列表,这种需求对于同个模型多个视图的框架来说是至关重要的。Swing组件负责将合适的模型Listener连接起来,以便于模型改变时能正确地重画出自己。如果你发现模型改变时,组件不能自动更新,说明组件的实现就存在错误。

忽略模型

        正如前面提到的,大多数组件直接在Component类中提供模型定义的API,以方便组件能不用和模型交互就直接操作,这是相当可行的编程方法,尤其是对于GUI状态模型来说。比如下面的JSlider内部getValue的实现,它将调用代理给模型:

public int getValue(){
      return getModel().getValue();
}

         因此程序完全可以这样写:

JSlider slider = new JSlider();
int value=slider.getValue();

Swing模型总结

         虽然理解了Swing模型设计是如何工作的,但没有必要在所有Swing编程中都使用模型API。你需要注意考虑应用程序各自的需求,决定哪儿使用模型API能帮你提升代码,且不带来不必要的复杂性。

         我特别推荐在Swing中使用应用数据模型(如JTable和JTree等的模型),因为从长期来看,它们能极大地提高你的应用程序可扩展性和模块化度。

         下一篇文章将就Swing框架的另一个概念UIDelegate进行阐述。



来源



以上文章版权由原作者所有。未经同意,不得将其任何一部分复制、转载、发布等未授权操作。


Java学习室 — 陈伟波个人主页
E-mail: zz3zcwb@sina.com
COPY RIGHT 2005