📄 s03.htm
字号:
<SCRIPT LANGUAGE="JavaScript" SRC="/-fs0/sys/pop-up.js"></SCRIPT><SCRIPT LANGUAGE="JavaScript" SRC="/-fs0/sys/pop-up-all.js"></SCRIPT><html><head><title>易都网--Java 2 图形设计卷Ⅱ:SWING</title><LINK rel="stylesheet" href="../../../_public/javaa.css"><meta http-equiv="Content-Type" content="text/html; charset=GBK"><script language="JavaScript" src="../../../_public/javaa.js"></script><meta name="keywords" content="Java,JSP,ASP,PHP,J2EE,EJB,JavaScript,C/C++,ASM,CSS,HTML,XML,网络安全,MySQL,ACCESS"></head><body bgcolor="#FFFFFF"><table border=0 cellpadding=0 cellspacing=0 width="100%"> <tbody> <script language="javascript">print2()</script> <tr> <td width="100%"> <table bgcolor=#EEEEEE border=0 cellpadding=3 cellspacing=0 width="100%"> <tbody> <tr> <td class=f1 id=thetd width="100%"> <p>[<a href="index.html" target="_self">目录</a>][<a href="s02.htm" target="_self">上一页</a>][<a href="s04.htm" target="_self">下一页</a>]</p> <p align="center"><b>第3章 Swing组件的体系结构</b></p> <p> 轻量Swing组件把它们的界面样式(look and feel)交给一个UI代表来处理,这个UI代表负责绘制组件(即look)并处理组件的事件(即feel)。可在构造组件之时或之后,把UI代表插入这个组件中。“插入式界面样式”这个术语在1.4节中介绍过。<br> Swing的插入式界面样式由一个基于Smalltalk的“模型-视图-控制器(Model-View-Controller,MVC)”设计的组件体系结构和用于管理界面样式的下层构件组成。前者是本章重点,首先我们给出典型的MVC的概览,然后再介绍Swing MVC的实现。后者稍后将在第7章中介绍。 </p> <p> <b><a name="3.1"></a>3.1 典型的“模型-视图-控制器”体系结构</b></p> <p> MVC体系结构是为那些需要为同样的数据提供多个视图的应用程序而设计的。MVC把应用程序分为三种对象类型:<br> ·模型:维护数据并提供数据访问方法。<br> ·视图:绘制模型的部分数据或所有数据的可视图。<br> ·控制器:处理事件。<br> 模型负责维护数据,例如,一个笔记本应用程序将把文档文本存储在模型中。模型通常提供访问和修改数据的方法。当模型变化时,这个模型还把事件发送给已登记的视图,对此,视图根据模型的变化来更新自己。<br> 视图负责提供模型的部分数据的可视图。例如,一个笔记本应用程序通过显示存储在模型中的部分文本或所有文本来提供当前文档的一个视图。<br> 控制器为视图处理事件。鼠标和动作监听器等AWT和Swing监听器都是MVC控制器。前面提到的笔记本应用程序应该有鼠标和键盘监听器,以便适时地改变模型或视图。<br> MVC需要很强的设计功能。首先,应当可以把多个视图和控制器插入到单个模型中,这是Swing插入式界面样式的基础。<br> 其次,当模型改变时,模型的视图能够自动地得到通知;在一个视图中改变模型的属性,将导致模型其他的视图也随之更新。<br> 最后,由于模型独立于视图,所以,不需要修改模型来适应新类型的视图或控制器。</p> <p> <b><a name="3.1.1"></a>3.1.1 插入式视图和控制器</b></p> <p> Swing(和AWT)容器把定位它们所包含的组件及确定这些组件的大小的工作委托给一个布局管理器。布局管理器封装了布局组件的策略。例如,FlowLayout布局管理器的策略是用组件的首选大小来安排组件的大小,并以从左到右、从上到下的顺序定位组件。<br> 封装的策略使它们是可插入的;例如,布局管理器可以在编译时,也可以在运行时刻插入到容器中。<br> 通过封装在视图中可视地表示数据的策略及封装控制器中处理事件的策略,MVC体系结构提供了可插入视图和控制器。就像布局管理器可以插入到AWT和Swing组件中一样,视图和控制器也可以插入到模型中。 </p> <p> <b><a name="3.1.2"></a>3.1.2 视图更新</b></p> <p> Swing(和AWT)事件由向事件源登记了的事件监听器来处理。例如,按钮的激活事件由一个对象所处理,这个对象实现ActionListener接口,并且通过调用这个按钮的addActionListener方法向这个按钮进行了登记(注:处理按钮动作事件的例子,请参见8.4节“JButton事件”)<br> 事件源和监听器是Observer样式的一个例子,Observer样式允许单个对象在所观察的对象修改时通知许多观察器。Observer样式需要在被观察对象与它的观察器之间有一个很小的接口区。例如,上面描述的动作监听器可以是任何类型的对象,只要它实现ActionListener接口。而且,按钮除了知道如何和何时通过观察器之外,对观察器一无所知。<br> 当模型改变时,MVC体系结构使用Observer样式来通知视图。模型可以有许多视图,所有的视图通常都用模型的通知来同步。而且,任何类型的视图都可以在不使模型本身有任务变化的情况下观察一个模型。<br> 图3-1示出了一个典型的MVC实现的信息流,并说明了在模型变化时,视图如何更新。<br> 事件由控制器处理,控制器根据事件的类型来改变模型或一个或多个视图。<br> 模型维护一个视图列表,这些视图为获得模型变化通知已经向模型登记过了。当模型发生变化时,该模型通知已向此模型登记的每个视图。视图通常从该模型中获得信息以进一步澄清这个事件,接着再更新它们自己。<br> <b>Swing提示</b><br> MVC的优点<br> 很久以来,MVC体系结构一直是建立Smalltalk应用程序的基础。<br> 面向对象开发的最基础的方面是确认抽象并在类中封装抽象。例如,一个工资册应用程序可能确认雇员、工资等抽象。在类中封装抽象允许在对象间建立松散的联系,这样就减少了依赖性,增加了灵活性和再使用性。<br> MVC封装了三个在大多数图形应用程序都存在的通用抽象:模型、视图和控制器。通过封装其他体系结构的优秀特性,MVC应用程序比相应的传统应用程序更灵活和更具有使用性。 </p> <p> <b><a name="3.2"></a>3.2 Swing MVC</b></p> <p> Swing MVC是典型MVC的专业版本,其设计目的是支持插入式界面模式而不是通用应用程序。Swing轻量组件由下面的对象组成:<br> ·一个维护组件的数据模型。<br> ·UI代表,它是一个带事件处理监听器的视图。<br> ·一个扩展JComponent的组件(注:参见第4章“JComponent”类)<br> Swing模型可以直接对应典型的MVC模型;这两个模型都维护数据并提供数据访问方法,在它们发生变化时,它们都通知监听器。<br> Swing组件把它们的界面样式交给一个UI代表来处理。UI代表与典型的MVC中的视图/控制器组合相对应。从现在开始,控制器又称作监听器。<br> Swing监听器通常作为UI代表的内部类来实现。例如,一个滑杆的UI代表实现一个响应模型变化的变化监听器。这个变化监听器是作为BasicSliderUI的内部类实现的:</p> <p> //From javax.swing.plaf.basic.BasicSliderUI.java:<br> public class BasicSliderUI extends SliderUI{<br> ...<br> //installUI is called when a UI is being installed<br> //for a component<br> public void installUI(JComponent c){<br> ...<br> changeListener = createChangeListener(slider);<br> ...<br> installListeners(slider);<br> }<br> ...<br> protected ChangeListener<br> createChangeListener(JSlider slider){<br> return new ChangeHander();<br> }<br> ...<br> protected void installListeners(JSlider slider){<br> ...<br> slider.getModel().addChangeListener(ChangeListener);<br> ...<br> }<br> ...<br> public class ChangeHandler implements ChangeListener{<br> public ovid stateChanged(ChangeEvent e){<br> if(!isDragging){<br> calculateThumbLocation();<br> slider.repaint();<br> }<br> }<br> }<br> ...<br> }</p> <p> BasicSliderUI创建了ChangeHandler的一个实例,该实例计算滑杆的滑块(即滑柄)的位置并重画该滑杆。<br> 根据组件所表现的复杂程度,组件代表可以有许多处理事件的内部类监听器。例如,BasicSliderUI类实现六个内部类监听器,如图3-2所示。</p> <p><b><a name="3.2.1"></a>3.2.1 Swing组件</b></p> <p> 组件为开发人员提供了一个API以操纵构成一个Swing组件的对象集。组件间接地创建它们的UI代表,并在适当的时候把任务交给这些UI代表。参见3.2.6节“组件UI的案件”,参见“UI代表绘制”中有关创建UI代表以及“安装一个UI代表”组件把绘制任务交给它们的UI代表的有关介绍。<br> 通过提供传递方法和通过传送模型事件,组件还使它们的模型对开发人员透明。<br> 1.模型传递方法<br> Swing组件为它们的模型提供传递方法,以便开发人员不需要直接访问模型来修改或查询状态。例如,下面列出的JSlider类的方法显示了滑杆是如何传递它们模型的最小值的。<br> //From JSlider.java,pass-through model methods;<br> public int getMinimum(){<br> return getModel().getMinimum();<br> }<br> public void setMinimum(int minimum){<br> int oldMin = getModel().getMinimum();<br> getModel().setMinimum(minimum);<br> firePropertyChange(" minimum",<br> new Intger(oldMin),new Integer(minimum));<br> }<br> JSlider.setMinimum()在设置最小值后激发一个属性变化事件。组件模型的所有属性(一个滑杆的最小值和最大值)都应该激发属性变化事件。<br> 2.传送模型事件<br> Swing组件还把模型事件传送给一个已向组件登记过的监听器。例如,一个滑杆作为一个变化监听器向其模型登记。当这个滑杆的模型激发了一个变化事件时,这个滑杆接着把一个变化事件发送给自己的变化监听器。JSlider类实现一个变化监听器,它只把一个状态变化事件发送给滑杆的变化监听器。与组件UI一样,JSlider等组件类常常在内部类中封装事件处理。<br> 下面列出了大大简化了的JSlider类进行监听的代码,其中说明了滑杆把状态变化发送给它们的监听器以响应模型状态的变化的方法(与其他Swing组件类的处理方法类似)。</p> <p> //From JSlider.java:<br> public class JSlider extends JComponent<br> implements SwingConstants,Accessible{<br> ...<br> protected ChangeListener changeListener=<br> createChangeListener();<br> ...<br> public JSlider(int orientation,int min,<br> int max,int value){<br> ...<br> sliderModel.addChangeListener(changeListener);<br> ...<br> }<br> public void addChangeListener(ChangeListener l){<br> listenerList.add(ChangeListener,class,l);<br> }<br> public void removeChangeListener(changeListener l){<br> listenerList.remove(Change Listener.class,l);<br> }<br> ...<br> protected ChangeListener createChangeListener(){<br> retrun new ModelListener();<br> }<br> ...<br> private class ModelListener<br> implements ChangeLister,Serializable{<br> public void stateChaged(ChangeEvent e){<br> //fire event to change listener registered<br> //with addChageListener() listed above<br> fireStateChanged();<br> }<br> }<br> }</p> <p> JSlider构造方法把一个JSlider.ModelListener实例添加到滑杆的模型中。JSlider.ModelListener通过调用JSlider.fireStateChanged()方法来对模型变化做出反应。JSlider.fireStateChaged()方法把一个变化事件发送给滑杆的监听器。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -