?? 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)??稍跇嬙旖M件之時或之后,把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 + -