概述Swing大多數(shù)控件
與VCL、AWT等框架中的圖形界面框架不同,Swing創(chuàng)造性的采用了MVC(Model View Controller) 模式。MVC 把控件(Component)劃分成三個部分:模型( Model):管理這個模塊中所用到的數(shù)據(jù)和值,如某個數(shù)據(jù)的最大值、最小值、當(dāng)前值等數(shù)據(jù);視圖( View):管理如何將模型顯示給用戶;控制器(Controller) 決定如何處理用戶和該模塊交互時產(chǎn)生的事件,如用戶單擊一個按鈕等。Sun 出于對視圖和控制器之間的依賴關(guān)系的考慮, 在 Swing 設(shè)計中將 MVC體系簡化為分離模型體系 ( Separable Model Architecture) , 將其中的控制器和視圖結(jié)合成 UI 代理。
◆界面中的每個控件都包含三種特征:
◆它的狀態(tài):比如一個按鈕的狀態(tài)
◆它的外觀:顏色、尺寸等
◆它的行為:對事件作出的反應(yīng)
以一個按鈕為例,它有可用、不可用狀態(tài),在不同的LookAndFeel中有不同的外觀顯示,在鼠標(biāo)按下、鼠標(biāo)右擊等事件中有自己獨(dú)特的響應(yīng)方式。如果管理按鈕狀態(tài)、繪制按鈕外觀,響應(yīng)時間等任務(wù)都由按鈕負(fù)責(zé)的話就違背了面向?qū)ο笤O(shè)計中的“單一責(zé)任原則”。Swing開發(fā)人員采用MVC模式解決了此問題,將控件的LookAndFeel同一個對象關(guān)聯(lián)到一起,同時將其內(nèi)容保存到另一個對象中??刂破髫?fù)責(zé)控制用戶輸入事件。比如鼠標(biāo)單擊、按鍵操作等,它會決定將這些事件轉(zhuǎn)換成模型中的改變.還是視圖中的改變。例如,假定用戶在文本框中按下某個鍵,控制器就會調(diào)用模型的“ 插入字符”命令。隨后,模型會通知視圖更新來顯示新的模型。視圖不用關(guān)心什么時候進(jìn)行文字改變,只要模型通知它更新它就會更新。這樣控制器只用與用戶交互并把交互結(jié)果反映到模型中去;模型負(fù)責(zé)維護(hù)狀態(tài),當(dāng)狀態(tài)變化時通知視圖更新顯示;視圖不負(fù)責(zé)用戶交互的狀態(tài)維護(hù),它只是根據(jù)模型中的狀態(tài)繪制不同的界面。
Swing大多數(shù)控件的模型是由一個名字以Model結(jié)尾的接口實現(xiàn)的。比如按鈕對應(yīng)的模型接口就是 ButtonModel,JDK中定義了ButtonModel的默認(rèn)實現(xiàn)類DefaultButtonModel。下面是ButtonModel各個方法的說明:
◆boolean isArmed():如果按鈕被按下,且鼠標(biāo)指針仍停留在按鈕上則返回true
◆boolean isSelected():如果按鈕處于選擇狀態(tài)則返回true
◆boolean isEnabled():如果按鈕可用則返回true
◆boolean isPressed():如果按鈕被按下,但鼠標(biāo)沒有松開,則返回true
◆boolean isRollover():如果鼠標(biāo)指針在按鈕之上則返回true
◆public int getMnemonic():返回按鈕的助記鍵
◆public String getActionCommand():返回命令字符串
此外還有對應(yīng)的設(shè)置狀態(tài)方法:public void setArmed(boolean b)、public void setSelected(boolean b)、public void setEnabled(boolean b)、public void setPressed(boolean b)、public void setRollover(boolean b)、public void setMnemonic(int key)、public void setActionCommand(String s)等。
每一個JButton都保存著一個ButtonModel對象,我們可以通過JButton的getModel方法來取得該模型對象:
◆JButton btn = new JButton(“test”);
◆ButtonModel btnModel = btn.getModel();
通過這個模型對象我們就可以得到按鈕的是否可用等狀態(tài),不過這個模型是給控件開發(fā)者使用的,對于普通使用者來說無需直接調(diào)用它,JButton提供了方法來間接的取得這些屬性,這一點可以從AbstractButton類的isSelected方法中看出來:
- public boolean isSelected()
- {
- return model.isSelected();
- }
Swing大多數(shù)控件都由自己的模型,比如JList控件的ListModel、JTable的TableModel、JSpinner的 SpinnerModel、JComboBox的SpinnerModel(SpinnerModel是從ListModel派生出來的),這些模型也由默認(rèn)的實現(xiàn),名稱通常為模型名前加Default。
Swing大多數(shù)控件的視圖是由一個名字以UI結(jié)尾的類實現(xiàn)的,比如按鈕對應(yīng)的模型接口就是 ButtonUI。由于視圖在不同的LookAndFeel中有不同的展現(xiàn)形式,所以控件的視圖對每一種LookAndFeel都提供了不同的實現(xiàn)。以 JLabel為例,它就有MetalLabelUI、MotifLabelUI、WindowsLabelUI等對應(yīng)不同LookAndFeel的實現(xiàn)。所有的視圖都要直接或者間接的從ComponentUI抽象類派生,ComponentUI類中的方法都是供Model回調(diào)使用的,下面是 ComponentUI主要方法的說明:
public void installUI(JComponent c):這個方法在ComponentUI 實例被安裝到UI代理的時候被觸發(fā),用來根據(jù)LookAndFeel配置控件。它需要完成如下工作:為Color、Font、Border、Icon等類型的屬性設(shè)定默認(rèn)值;根據(jù)需要設(shè)置布局管理器;創(chuàng)建子控件;初始化監(jiān)聽器;為控件設(shè)置PropertyChangeListener 監(jiān)聽器以檢測控件屬性變化事件;初始化快捷鍵、Tab鍵順序等;初始化數(shù)據(jù);
public void uninstallUI(JComponent c):這個方法在ComponentUI 實例被從UI代理移除的時候觸發(fā)。需要在此方法中撤銷任何在installUI中進(jìn)行的配置,要保證JComponent實例變?yōu)闈崈魻顟B(tài)(也就是沒有監(jiān)聽器,沒有LookAndFeel專有屬性等)。它需要完成如下工作:從控件中移除border;從控件中移除布局管理器;從控件中移除子控件;從控件中移除事件、屬性監(jiān)聽器、從控件中移除快捷鍵、Tab鍵順序等;將數(shù)據(jù)標(biāo)記為可以垃圾回收。
◆public void paint(Graphics g, JComponent c):為本視圖的LookAndFeel繪制控件。
◆public void update(Graphics g, JComponent c):通知UI代理繪制指定控件。當(dāng)特定的控件被繪制的時候此方法會被觸發(fā)。這個方法的默認(rèn)實現(xiàn)是用背景色填充控件,并且立即調(diào)用paint方法。
◆public Dimension getPreferredSize(JComponent c):返回當(dāng)前LookAndFeel下控件的最佳尺寸。默認(rèn)實現(xiàn)是返回null;
◆public Dimension getMinimumSize(JComponent c):返回當(dāng)前LookAndFeel下控件的最小尺寸。默認(rèn)實現(xiàn)是返回getPreferredSize的值;
◆public Dimension getMaximumSize(JComponent c):返回當(dāng)前LookAndFeel下控件的最大尺寸。默認(rèn)實現(xiàn)是返回getPreferredSize的值;
◆public boolean contains(JComponent c, int x, int y):判斷指定的x、y坐標(biāo)是否存在于當(dāng)前LookAndFeel下的控件中。
◆public static ComponentUI createUI(JComponent c):為指定的控件返回UI代理實例。如果UI代理子類是無狀態(tài)的,它也可以返回多控件共享的實例。如果UI代理子類是有狀態(tài)的,則它必須為某個控件返回一個新的實例。
◆public int getAccessibleChildrenCount(JComponent c):返回所有可訪問子控件的數(shù)量。
◆public Accessible getAccessibleChild(JComponent c, int i):返回指定的子控件
【編輯推薦】