核心Swing組件(一) – JAVA編程語言程序開發技術文章

在第3章,我們簡要介紹瞭JFC/Swing工程組件所用的Model-View-Controller(MVC)模式。在本章中,我們將會開始探討如何使用許多可用組件中的關鍵部分。


所有的Swing組件都是以JComponent類為起點的。盡管Swing庫的某些部分並不以JComponent類為根,但所有的組件在其繼承的某些級別上共享JComponent類作為通用父類。JComponent類定義通用的行為與屬性。在本章中,我們將會瞭解一些通用功能,例如組件繪制,自定義義,工具提示以及變化大小。


隨著特定JComponent子孫類被關註 ,我們將會特別瞭解JLabel,JButton以及JPanel,三個更為廣泛使用的Swing組件類。為瞭組件內顯示圖像,我們需要理解Icon接口,以及當使用預定義圖像時的ImageIcon類與GrayFilter類的支持。另外,我們將會瞭解AbstractButton類,他是JButton類的父類。所有的AbstractButton的子類所共享的數據模型是ButtonModel接口;我們將會探討這個接口及其特定實現,DefaultButtonModel。


4.1 JComponent類


JComponent類是所有的Swing組件繼承的抽象基類。JComponent類有42個派生子類,每一個都繼承瞭JComponent的功能。圖4-1顯示瞭繼承層次結構。


盡管JComponent類是所有Swing組件的共同基類,但是Swing工程庫中的許多類並不是由JComponent類派生類。這包括所有的高層窗口對象,例如JFrame,JApplet以及JInternalFrame;所有的MVC相關的類;事件處理相關的接口與類;等。所有這些類將會後面的章節中進行討論。


盡管所有的Swing組件擴展JComponent,JComponent類擴展AWT的Container類,相應的,其擴展AWT的Component類。這就意味著許多的JComponent方面都是由AWT的Component與Container類所共享的。


4.1.1 組件分片


JComponent類定義瞭許多超出原始的AWT組件集合功能的AWT組件面。這包括自定義繪制行為以及自定義顯示設置的不同方法,例如顏色,字體以及其他的客戶端設置。


繪制JComponent對象


因為Swing的JComponent類是由Container類擴展而來的,因而會遵循基本的AWT繪制模型:所有的繪制都是通過paint()方法來完成的,而repaint()方法則用來觸發更新。然而,許多任務的完成是不同的。JComponent類優化瞭繪制的許多方面從而改進性能與可擴展性。另外,RepaintManager類可以用來自定義繪制行為。


為瞭改進繪制性能與擴展性,JComponent將繪制操作分為三個任務。public void paint(Graphics g)方法被分為三個獨立的protected方法調用。由調用的順序,他們依次為paintComponent(g), paintBorder(g)以及paintChildren(g),通過原始的paint()調用傳遞Graphics參數。組件本身首先通過paintComponent(g)進行繪制。如果我們希望自定義Swing組件的繪制,我們可以重寫paintComponent()方法而不是paint()方法。除非我們希望完全替換所有的繪制,我們需要首先調用super.paintComponent(),正如下面所示的,來獲得默認的paintComponent()行為。


public class MyComponent extends JPanel {
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Customize after calling super.paintComponent(g)
}

}

paintBorder()與paintChildren()方法是不可重寫的。paintBorder()方法繪制組件周圍的邊框,第7章會對其概念進行更為完全的描述。如果在Swing容器對象內存在組件,則paintChildren()方法會繪制這些組件。


為瞭優化繪制,JComponent類提供瞭三個額外的繪制屬性:opaque, optimizedDrawingEnabled以及doubleBuffered。其作用如下:



  • Optacity:JComponent的opaque屬性定義瞭一個組件是否透明。當透明時,JComponent容器必須在組件之後繪制背景。為瞭改進性能,我們可以保留JComponent的不透明物並使得JComponent繪制其背景,而不要依賴於容器來繪制被覆蓋的背景。
  • Optimization:optimizedDrawingEanbled屬性緊鄰的子元素是否可以重疊。如果子元素不可以重疊,可以極大的減少重繪時間。在默認情況下,優化繪制對於絕大多數的Swing組件是允許的,除瞭JDesktopPane,JLayeredPane以及JViewport。
  • Double buffering:在默認情況下,所有的Swing組件會將他們的繪制操作重復緩存到一個完整的容器層次結構所共享的緩沖區中;也就是,在一個窗體內的所有組件。這極大的改善瞭繪制性能,因為當允許雙緩沖時(通過doubleBuffered屬性),隻有一個屏幕更新繪制。

JComponent的public void revalidate()方法也提供繪制支持。當這個方法被調用時,組件的高級容器會驗證其本身。這與AWT的直接調用高級組件的revalidate()方法不同。


Swing組件繪制加強的最後一個方面就是RepaintManager類。


RepaintManager類


RepaintManager類負責保證當前顯示的Swing組件之上的重繪請求的高效,確保當一個區域無效時隻更新屏幕的最小“臟”區域。


盡管不能進行自定義,RepaintManager是公開並且提供瞭一個靜態的安裝例程來使用自定義管理器:public static void setCurrentManager(RepaintManager manager)。要獲得當前的管理器,隻需要調用public static void currentmanager(JComponent)方法。參數通常為null,除非我們已經自定義瞭管理器來提供組件級別的支持。一旦我們擁有管理器在,我們可以做的一件事就是將屏幕緩沖區獲取為圖像。因為緩沖區就是實際顯示在屏幕上的內容,這可以使得我們高效的實現窗體內部的屏幕復制。


Component comp = …
RepaintManager manager = RepaintManager.currentManager(null);
Image htmlImage = manager.getOffscreenBuffer(comp, comp.getWidth(),
comp.getHeight());
// or
Image volatileImage = manager.getVolatileOffscreenBuffer(comp, comp.getWidth(),
comp.getHeight());

表4-1顯示瞭RepaintManager的兩個屬性。他可以使得我們禁止一個組件(層次結構)的所有繪制操作的雙緩沖,並且設置最大的雙緩沖尺寸,默認為終端用戶的屏幕尺寸。


RepaintManager屬性















屬性名
數據類型

可訪問性

doubleBufferingEnabled
boolean

讀寫

doubleBufferMaximumSize
Dimension

讀寫


盡管很少實現,提供我們自己的RepaintManager子類確實允許我們自定義屏幕臟區域的繪制機制,或者是當繪制完成時的最少跟蹤。重寫下面四個方法的一個可以允許我們自定義機制:


public synchronized void addDirtyRegion(JComponent component, int x, int y,
int width, int height)
public Rectangle getDirtyRegion(JComponent component)
public void markCompletelyClean(JComponent component)
public void markCompletelyDirty(JComponent component)

UIDefaults類


UIDefaults類表示為當前的觀感所安裝的包含顯示設置的查詢表,例如JList中所用的字體,在JTree節中所顯示的顏色或圖標。UIDefaults的使用將會在第20章探討Java可插撥的觀感體系結構時進行詳細討論。在這裡,我們隻是簡要介紹UIDefaults表。


當我們創建一個組件時,組件會自動的請求UIManager在UIDefaults表中查找組件所用的當前設置。大多數的顏色,字體相關的組件設置,以及其他的一些與顏色與字體無關的設置,都是可配置的。如果你不喜歡一個特定的設置,我們可以簡單的通過更新UIDefaults查詢表中的相應項目進行修改。


首先我們需要知道我們希望修改的UIDefaults設置的名字。我們可以在本書的附錄A中找到這些設置名字,在這個附錄中包含J2SE 5.0中預定義觀感的所有已知設置的完整列表。(由於發行版本的不同會略有不同。)另外,包含有每個組件描述的是一個包含UIResource相關屬性元素的表。(要查找本書中特定組件部分,請查看內容表或是索引。)


一旦我們知道瞭設置的名字,我們可以使用UImanager的public static void put(Object key, Object value)方法來存放一個新的設置,其中key是鍵值字符串。例如,下面的代碼會將新創建的按鈕的背景顏色改變黑色,而前景色改變紅色:


UIManager.put(“Button.background”, Color.BLACK);
UIManager.put(“<SPAN

發佈留言