Swing


          天行健 君子以自強不息

          posts - 69, comments - 215, trackbacks - 0, articles - 16
             :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          Swing模型與渲染器

          Posted on 2007-10-12 10:35 zht 閱讀(1698) 評論(0)  編輯  收藏
                  本文承接Swing/AWT/SWT比較一文,概要敘述Swing的體系結(jié)構(gòu),解釋了Swing架構(gòu)關(guān)鍵概念:模型與渲染器,解釋如何使用渲染對象擴展該體系架構(gòu)來支持大數(shù)據(jù)量的組件。后面的文章還會簡要概述SWT的體系結(jié)構(gòu),為Swing/AWT和SWT的比較做一鋪墊。

          =====================================

                   Java基礎(chǔ)類(JFC)Swing工具提供了使用Java平臺創(chuàng)建高度可交互性圖形用戶界面的類。Swing是高度靈活的,但是也因此相當(dāng)復(fù)雜,雖然新手能夠使用Swing創(chuàng)建基本的圖形用戶界面(GUI),但是真要創(chuàng)建一個復(fù)雜、專業(yè)的GUI界面,你必須理解Swing的體系架構(gòu)的基礎(chǔ),尤其是使用 Swing創(chuàng)建復(fù)雜、像JTable、JTree、JComboBox以及JList這樣基于渲染器的組件,Swing提供的基于模型和渲染器的組件是構(gòu)建高性能、可擴展GUI的關(guān)鍵。

          Swing體系結(jié)構(gòu)

                   最初Smalltalk系統(tǒng)的UI工具使用所謂的模型-視圖-控制(MVC)模式,MVC引入這樣一個概念:數(shù)據(jù)源應(yīng)該同屏幕展現(xiàn)分開。這是一個優(yōu)秀的體系設(shè)計結(jié)構(gòu),能促進(jìn)代碼重用和程序框架。Swing使用的是一個變體的MVC架構(gòu),如圖所示:

          http://s2.album.sina.com.cn/pic/4b6047bc02000kk1

                   典型的Swing GUI組件包括至少三個對象:一個Component,一個Model和一個UI Delegate,在這個框架中,Model負(fù)責(zé)存儲數(shù)據(jù),UI Delegate負(fù)責(zé)從Model獲取數(shù)據(jù)并渲染到屏幕上去,Component通常協(xié)調(diào)Model和Delegate之間的操作,并同時負(fù)責(zé)將 Swing嵌入到AWT窗口系統(tǒng)中。

                   注意,UI Delegate對象可以在運行的時候動態(tài)替換,這就使Swing具備了可插拔的外觀(Pluggable Look-And-Feel, PLAF)。

                   雖然Swing的MVC結(jié)構(gòu)顯然具備靈活性的好處,但是這個結(jié)構(gòu)通常被指責(zé)為一些程序慢的根源。雖然基于MVC結(jié)構(gòu)需要更多的方法調(diào)用來支持額外的重定向,其實花費在這兒的消耗很小。對基于Swing的應(yīng)用程序profile的結(jié)果顯示,model-view分隔的開銷可以忽略不計,不到CPU總開銷的 1%,復(fù)雜的Swing用戶界面的多數(shù)處理事件其實都花費在了底層的圖形操作上了。Swing的model-view結(jié)構(gòu)并不是低性能的根源,它是構(gòu)建可擴展程序的關(guān)鍵。

          矢量組件

                   Swing提供了一些處理大數(shù)據(jù)量數(shù)據(jù)集的組件,包括JTable、JTree、JList以及JComboBox。這些矢量組件被設(shè)計成能夠處理成千上萬甚至數(shù)百萬的數(shù)據(jù),為了避免占用大量內(nèi)存,這些組件在Swing的體系架構(gòu)增加了渲染器(renderer)概念。下圖是增加了渲染器結(jié)構(gòu)的Swing 體系架構(gòu)。

          http://s3.album.sina.com.cn/pic/4b6047bc02000kk2

          渲染器(Renderer)

                   在這些更為復(fù)雜的Swing組件中,渲染器是提供可擴展性的關(guān)鍵。我們以JTable作為渲染器的示例。缺省表格中的每一格可能都有一個JLabel,這對于比較小的數(shù)據(jù)集來說可行,但是對于大數(shù)據(jù)集就行不通。比如,如果使用這種表格顯示1000x1000的數(shù)據(jù)集,需要的內(nèi)存可能要1G,即使每個格子都是空的。

                   如果解決這種擴展性問題?Swing的JTable使用一個組件來畫出所有相同類型的格子。比如所有的String對象的格子都使用相同的組件畫。這種類型的組件被稱作渲染器(renderer),使用渲染器顯示多個表格極大的減小了大型數(shù)據(jù)表存儲空間。

                   當(dāng)渲染器用來顯示表格時,JTable從model中獲取格子中的數(shù)據(jù),然后使用這些數(shù)據(jù)對渲染器進(jìn)行配置,然后使用該渲染器畫出該格子。接下來,渲染器繼續(xù)移動到下一個格子,然后重復(fù)這個過程。

                   注意你可以通過操作渲染器和模型來控制這個過程,所有的矢量組件,包括JTree、JList以及JComboBox都使用渲染器方法,并不僅限于JTable。

          模型(Model)

                   直接操作Swing的模型(Model)對于編寫可擴展的用戶界面至關(guān)重要,下面代碼是往JComboBox添加數(shù)據(jù)項的通常做法:

          JComboBox box = new JComboBox();
          for (int i = 0; i < numItems; i++) {
              box.addItem(new Integer(i));
          }

                   這些代碼只是簡單的往JComboBox中添加數(shù)據(jù)項,代碼同往AWT的Choice中添加選項類似,這種方法對于小數(shù)據(jù)量來說可以,但是當(dāng)要添加大量數(shù)據(jù)時就會明顯變得非常慢。

                   盡管上面的代碼沒有明確引用任何模型,JComboBox的模型對象實際上參與這個過程,每次調(diào)用addItem時,JComboBox內(nèi)部發(fā)生了許多操作:組件將請求傳遞給JComboBox的模型,模型發(fā)送一個事件表明一個新項被添加。很明顯,如果你直接操作模型的將會更高效,如下例所示:

          Vector v = new Vector(numItems);
          for (int i = 0; i < numItems; i++) {
             v.add(new Integer(i));
          }
          ComboBoxModel model = new DefaultComboBoxModel(v);
          JComboBox box = new JComboBox(model);

                   這樣為什么會更快呢?原因有兩個。第一,因為所有項是一次添加到模型去,而不是一個一個的,只有一個事件發(fā)出,這意味著更少的事件觸發(fā),更少的方法調(diào)用。第二是因為需要通知變化的對象更少,總的工作量等于觸發(fā)次數(shù)乘以偵聽器數(shù)目。因為模型是新創(chuàng)建的,偵聽在上面的偵聽器為零,這意味著沒有觸發(fā)事件發(fā)生。

                   從上面的例子可以學(xué)到兩點:

          • 盡可能使用批操作,盡量減少觸發(fā)事件的數(shù)量。

          • 當(dāng)初始化或者需要完全替換模型的內(nèi)容時,考慮重新生成模型,不要使用已經(jīng)存在的模型,已存在模型上已經(jīng)保持了很多的偵聽器,新生成的模型沒有偵聽器,這樣避免了不必要的處理函數(shù)的調(diào)用。

                       觸發(fā)事件數(shù)量嚴(yán)重影響你的程序啟動時間,也會影響打開對話框和相似操作的時間。

          =====================================

                    本想詳細(xì)舉幾個例子進(jìn)一步說明模型和渲染器的用法和好處,但網(wǎng)絡(luò)速度還是太慢,寫一篇文章太痛苦了...加上篇幅原因,準(zhǔn)備以后再寫一文,彌補這方面的知識。

                    以后幾篇文章包括(非文章標(biāo)題):

          • 使用Swing模型和渲染器優(yōu)化Swing程序。

          • Swing/AWT事件處理模型以及線程安全。

          • 如何編寫響應(yīng)快速的Swing程序。

          • SWT設(shè)計和實現(xiàn)介紹。

          • JNI與Java性能的關(guān)系。

          • 垃圾收集與虛擬機與Java性能。

          • Swing與SWT性能比較(前面所有的文章都和這篇有關(guān),是基礎(chǔ))。

          主站蜘蛛池模板: 南皮县| 海阳市| 和林格尔县| 克拉玛依市| 亳州市| 罗田县| 成都市| 天峻县| 开原市| 嘉祥县| 石城县| 光山县| 依兰县| 福州市| 花莲市| 南华县| 方山县| 固原市| 云安县| 宁德市| 崇文区| 开远市| 梅河口市| 永善县| 平定县| 登封市| 贵德县| 濮阳市| 成武县| 沅江市| 墨脱县| 岳普湖县| 廊坊市| 泰顺县| 邹平县| 平顶山市| 余干县| 肥东县| 莱阳市| 翼城县| 六枝特区|