技術改變世界

           

          Swing第二刀:枝間新綠一重重

          關于綠色

                  喜歡綠色,喜歡雅黑,無可救藥。在這個吵吵鬧鬧的軟件行業,綠色也忽然從“春風一拂千山綠”唯美變成俗不可耐的buzzword。比如:

                  綠色軟件:大大的buzzword。忽然一夜之間,所有的軟件都綠色了,好像不“綠”就跟不上形勢。比如綠色殺毒,綠色OFFICE,綠色ERP,綠色windows。反正全綠。

                  綠色征途:看,精神鴉~片也可以很“綠”的;

                  綠~壩-花季護航:呃,老好的軟件,不多說了;

                  綠色世博:嗯,喊的老響了。至今一頭霧水。

                  綠色還有一些不好的詞,比如人人避之不及的“綠帽子”之類。臺灣的綠營也代表了大壞蛋那幫人(至少陳水扁帶了個頭)。還有“我把老板氣的臉都綠了”、”老板整天燈紅酒綠“,也都不是什么好詞。
                  不過綠色更多的還是代表了“春天、自然、環保、低碳”等沒好的東西。皮尤慈善信托基金(Pew)在一份名為《綠色改變世界》的研究報告中指出,計算機屏幕如果使用綠色可以節省大量電能并降低輻射,保護使用者雙眼和皮膚。例如一個全屏顯示的綠色軟件界面可以讓一臺液晶顯示器消耗功率降低13.7瓦;假設美國電腦擁有量為5299萬臺來計算,每年僅關機狀態功耗一項可以節約 6.2億度電。如果我們把所有的軟件都設計成“綠色”這個環保色,每臺計算機都會減少5%的電能和輻射,人的情緒也會更加平緩舒暢,心臟和雙肺由此減少12%的血液循環負擔,從而降低人類對氧氣的需求和二氧化碳的呼出達到14%。加上節省下來的對皮膚護理保養、心肺疾病治療、近視以及眼鏡相關行業對自然資源的消耗,每年全球可以節省1400億美元的資源消耗,相當于減少砍伐8500平方公里的亞馬遜熱帶雨林,對于處于正在復蘇之中的世界經濟具有說一不二的作用。看來,“綠色軟件”,先把自己的界面搞“綠”了,就是地球的一大幸事!
                  (注意:上述報告和數據純屬胡謅八扯,如有雷同,純屬巧合。)
                  但是制作一個綠色的軟件界面確實一個心愿。尤其是能夠體現“枝間新綠一重重,小蕾深藏數點紅”的那種感覺!現在終于有了,經過一個多星期的折騰,終于有了一個雛形,在上一篇博文《Swing是一把刀》中給大家看到的:




          框架,還是框架


                  這個程序的設計初衷是快速建立一個美觀的Swing應用程序外觀。但是,具體來說,它又并非完全是下面幾個東西:

                  LookAndFeel:這個程序并非一個LnF。一個LnF會對所有的Swing組件進行重新定義Paint并可以通過UIManager.setLookAndFeel進行啟用。這個程序用到了大量LookAndFeel的機制,甚至也直接定義了不少UI。不過它并不是一個完整的LookAndFeel。這些定制完全是為這個程序框架服務的。也就是說,這些UI和重繪機制只有在當前的程序框架起作用,而無法指望一句UIManager.setLookAndFeel就將你的任意Swing程序變成上圖風格。

                  組件庫:也不是組件庫。其實里面的組件,除了這個OutlookPane(左側的模塊樹)是完全新做出來的(而且沒有從JTabbedPane繼承,也許理論上還經不起太嚴謹的推敲),其他的組件都是很簡單、現成的。例如列表、按鈕、菜單等,都是直接用Swing的,只是重載了一些方法或者定義了UI而已。而且我并非是想讓大家直接new OutlookPane()這樣來使用,而是使用XML文件對整個界面進行配置使用;

                  GUI程序框架:似乎有點大。這僅僅是一個很小的程序而已。

                  做Java的喜歡滿嘴Framework。你要是不能氣定神閑一口氣提到20個Framework并有意無意的暗示自己很精通,那~都不好意思跟人家說話;最好再能挑一個有點名氣的,指手畫腳、評頭論足、怒其不爭一下下,那就像大牛了(例如Hibernate就是個很不錯的candidate)。所以,咱這個小程序也就死乞白賴往“框架”上湊湊,反正已經帶上了“綠帽子”,也不怕丟人丟到底。

                  好吧,這是一個框架,雖然我也不知道框架該怎么定義。反正我的設計初衷是:如果你用Swing開發一個類似上圖結構的應用程序,那么你可以直接用這個框架。這個程序框,包含了上面菜單、地下狀態條、左邊模塊欄、右邊功能快捷列表,中間多tab標簽頁的各種內容(也提供了幾個常用的內容頁風格,例如列表、流程圖等)。這個窗口已經被封裝好,通過XML配置文件來定義菜單、狀態條、模塊欄、流程圖、右邊的快捷列表。同時,這些都是聯動的。例如:點擊左邊的模塊欄中的子模塊,一個對應的流程圖會顯示在中間tab頁;選中流程圖中的節點,可以把該節點相關的功能列在右側。點擊右側列表,可以執行各種定義好的動作(動作通過動作碼定義,后面會詳細介紹)。使用么,直接new 一個窗口類,set各個部分的XML文件名,然后setVisible(true)就OK了。至于中間的各個組件和大家關心的LookAndFeel,則都定義好了,基本上不用太關心細節。

                  不管怎么說,我們就叫它“框架”吧。

          XML配置

                  每個應用程序都千奇百怪,功能各異。如何用一個同樣的界面來組織呢?的確,這個界面并非適合所有人。不過這里的所有菜單、按鈕、流程圖、圖標等,其動作都是可以用一個“動作碼”類定義的,所有的動作都會回調一個統一的函數。而我們只要在這個函數處插入監聽,就可以攔截具體動作碼,執行我們想做的任何事情,例如格式化C盤、往aobama@whitehouse.com郵箱發個垃圾郵件啥的。

                  例如,要定義主菜單,通過這個XML:

           1   <?  xml version="1.0" encoding="UTF-8"  ?>    
           2
           3    <  menubar  >    
           4
           5      <  menu   text  ="System"   >    
           6
           7        <  menu   text  ="One Sub Module"   >    
           8
           9          <  menuitem   text  ="Test Report Item"   tooltip  ="Tooltip"    icon  ="/free/email.png"   action  ="A001"   />    
          10
          11          <  menuitem   text  ="Test Report Item"   tooltip  ="Tooltip"   icon  ="/free/email.png"   action  ="A001"   />    
          12
          13          <  menuitem   text  ="Test Report Item"   tooltip  ="Tooltip"   icon  ="/free/email.png"   action  ="A001"   />    
          14
          15          <  menuitem   text  ="Test Report Item"   tooltip  ="Tooltip"    icon  ="/free/email.png"   action  ="A001"   />    
          16
          17    
          18
          19      </  menu  >    
          20
          21    </  menubar  >   
          22

                  以上XML可以定義一個System的主菜單,以及一個One Sub Module的菜單項,以及一系列的二級菜單。每個菜單都可以設置icon圖標、文字、tooltip文字,以及動作碼(就是那個action)。如下圖:



                  左側的模塊欄就是典型的Outlook的風格,很多軟件干脆都叫它OutlookPane(我這里也是如此)。這個OutlookPane的配置,通過如下類似XML:

          <outlook>  

             
          <module text="Engineering Box" 

                            icon
          ="/free/test/module_unselected.png" 

                            selected_icon
          ="/free/test/module_selected.png" 

                            network
          ="network.xml">  

             
          </module>  

           
          </outlook> 
                  
                  同樣,主模塊(也就是每個大分欄)包含了模塊欄的文字、icon圖標(選中和未選中兩個),以及一個xml文件。這個xml文件包含了一個流程圖,流程圖包含了具體的子模塊。點擊展開大模塊欄后,所有的子模塊也會顯示在欄目中,同時模塊的流程關系會通過對應的xml文件中定義的方式,顯示在一個圖形化的流程圖界面中,最終顯示在中間的tab頁上。


                  可以看到,左側的模塊列表和中間的圖形節點是一一對應的。當鼠標選中節點后(變成橙色),左側的列表對應的項也會被選中。同時,和這個節點(代表了一個具體子模塊)相關的功能,都會顯示在右側的快捷列表中(這是通過指向的network.xml文件定義的)

                  上面例子中的Network.xml內容舉例如下:

            1<?xml version="1.0" encoding="UTF-8"?>  
            2
            3 <network>  
            4
            5     <node x="30" y="50" 
            6
            7           text="AP Prepay" 
            8
            9           network_text="AP Prepay" 
           10
           11           tooltip="This is a tooltip of a node" 
           12
           13           icon="/free/test/module.png" 
           14
           15           list_icon="/free/test/submodule.png">  
           16
           17         <button1 tooltip="Tooltip" 
           18
           19                             icon="/free/test/module_attachment.png" action="X002"/>  
           20
           21         <button2 tooltip="Tooltip" 
           22
           23                             icon="/free/test/module_attachment.png" action="X002"/>  
           24
           25         <button3 tooltip="Tooltip" 
           26
           27                             icon="/free/test/module_attachment.png" action="X002"/>  
           28
           29         <shortcuts>  
           30
           31             <separator text="Most Often Used Reports"/>  
           32
           33             <shortcut text="Add a Part" tooltip="Tooltip" 
           34
           35                             icon="/free/submodule.png" action="Z010"/>  
           36
           37             <shortcut text="Delete a Part" tooltip="Tooltip" 
           38
           39                             icon="/free/submodule.png" action="Z010"/>  
           40
           41             <shortcut text="AP Aging Report" tooltip="Tooltip" 
           42
           43                             icon="/free/chart.png" action="Z010"/>  
           44
           45             <shortcut text="MRP for All Parts Used this Month" tooltip="Tooltip" 
           46
           47                             icon="/free/user.png" action="Z010"/>  
           48
           49             <shortcut text="Dashboard of this Month" tooltip="Tooltip" 
           50
           51                             icon="/free/email.png" action="Z010"/>  
           52
           53             <shortcut text="All Open Purchase Orders" tooltip="Tooltip" 
           54
           55                             icon="/free/chart.png" action="Z010"/>  
           56
           57             <shortcut text="Search in Address Book" tooltip="Tooltip" 
           58
           59                             icon="/free/user.png" action="Z010"/>  
           60
           61             <shortcut text="All Online Users" tooltip="Tooltip" 
           62
           63                             icon="/free/email.png" action="Z010"/>  
           64
           65             <separator text="Common Reports"/>  
           66
           67             <shortcut text="All Open Purchase Orders" tooltip="Tooltip" 
           68
           69                             icon="/free/chart.png" action="Z010"/>  
           70
           71             <shortcut text="Search in Address Book" tooltip="Tooltip" 
           72
           73                             icon="/free/user.png" action="Z010"/>  
           74
           75             <shortcut text="All Online Users" tooltip="Tooltip" 
           76
           77                             icon="/free/email.png" action="Z010"/>  
           78
           79             <shortcut text="All Open Purchase Orders" tooltip="Tooltip" 
           80
           81                             icon="/free/chart.png" action="Z010"/>  
           82
           83             <shortcut text="Search in Address Book" tooltip="Tooltip" 
           84
           85                             icon="/free/user.png" action="Z010"/>  
           86
           87             <shortcut text="All Online Users" tooltip="Tooltip" 
           88
           89                             icon="/free/email.png" action="Z010"/>  
           90
           91             <shortcut text="All Open Purchase Orders" tooltip="Tooltip" 
           92
           93                             icon="/free/chart.png" action="Z010"/>  
           94
           95             <shortcut text="Search in Address Book" tooltip="Tooltip" 
           96
           97                             icon="/test/user.png" action="Z010"/>  
           98
           99             <shortcut text="All Online Users" tooltip="Tooltip" 
          100
          101                             icon="/free/email.png" action="Z010"/>  
          102
          103         </shortcuts>  
          104
          105     </node>  
          106
          107 </network> 
          108

                  其中,每個node定義了一個子模塊節點。節點上包含x、y坐標信息、文本信息、tooltip、icon圖標(中間大的主圖標),以及三個按鈕。每個node如圖所示,可以攜帶3個按鈕。每個按鈕可以掛一個圖標、tooltip、icon以及動作碼。我們可以定義其任意動作。


                   
                  然后,每個node又攜帶了一個shortcuts列表,包含了這個節點所有相關的功能點,在node被選中后,以右側的列表方式列出。如圖所示:



                  此外,流程圖中的箭頭是通過類似如下XML在network.xml中定義:

          <arrow x="170" y="80" direction="left" rotation="0"/>

                  其中x、y是坐標,direction是方向,可以是上下左右以及斜向共8個方向。此外rotation還提供了旋轉角度。如果right_up這個45度的右上角度不符合要求,可以在增加rotation進行進一步調節。

                  右側快捷列表的分割文字,也是通過如下xml進行定義:

          <shortcuts>  

                       
          <separator text="Most Often Used Reports"/>  

                       
          <shortcut text="Add a Part" tooltip="Tooltip" 

                                       icon
          ="/free/test/submodule.png" action="Z010"/>  

            

                  分隔條可以攜帶一個文字,用來對很多列表項進行分組:


                  還有工具條也是可以配置的。工具條在這個框架里被放在了模塊欄的頂部。通過如下XML配置其按鈕:

           1<?xml version="1.0" encoding="UTF-8"?>  
           2
           3 <toolbar>  
           4
           5     <button tooltip="Tooltip" icon="/free/test/message.png" action="B001" />  
           6
           7     <separator/>  
           8
           9     <button tooltip="Tooltip" icon="/free/test/user.png" action="B001" />  
          10
          11     <separator/>  
          12
          13     <button tooltip="Tooltip" icon="/free/test/email.png" action="B001" />  
          14
          15     <separator/>  
          16
          17     <button tooltip="Tooltip" icon="/free/test/viewer.png" action="B001" />  
          18
          19     <separator/>  
          20
          21     <button tooltip="Tooltip" icon="/free/test/chart.png" action="B001" />  
          22
          23     <separator/>  
          24
          25     <button tooltip="Tooltip" icon="/free/test/capture.png" action="B001" />  
          26
          27     <separator/>  
          28
          29     <button tooltip="Tooltip" icon="/free/test/image_edit.png" action="B001" />  
          30
          31     <separator/>  
          32
          33 </toolbar> 
          34

                  其中<separator>定義了一個分割豎線 ,完全美觀之用。顯示效果如下:



                  最后一個配置項是軟件右上角的LOGO。每個系統都想有一個地方漂亮的顯示咱家的LOGO,那才有成就感!這里通過menubar菜單的XML文件如下配置:

          <logo image="/free/test/logo_company.png" tooltip="WPT Power Transmission" />

                  可以對圖片、tooltip進行定義。顯示效果如下:


                  這樣,一個完整的”純綠色“應用程序框架就差不多被”配置“出來了。

          程序接口

                  其實設計初衷是無需使用源代碼,直接使用下方提供的jar包即可進行二次開發。因為畢竟通過XML就可以對界面元素進行定義了。如果要把這個框架集成到你的應用程序中,并執行你的具體動作,只需要對free.Shell這個類進行一個函數重載即可。

          public void command(String action) {  

                   String message 
          = "Perform action " + action + ".";  

                   
          this.lbStatusMessage.setText(message);  

           }
           

                  在Shell這個類中,界面上所有的按鈕、菜單、列表等被點擊后,都會回調這個Shell的command方法,并傳回action字符串,也就是我們在XML中定義的動作碼。接著你就用if else或者case啥的進行處理動作吧!當然也可以調用addTab方法在Shell界面中添加一個tab頁面。其使用方法會下次詳細闡述。

          關于效率、內存、布局和其他

                  有朋友說很擔心執行效率、內存占用。這是對Swing常被攻擊的的一個老話題了。簡單直接的回答是:Swing效率沒問題。內存占用沒問題。滿眼嘩嘩一片字符串,就一定占內存嗎?table有1000行,渲染的花里胡哨,就內存問題嗎?完全不是這么一回事。例如,如果你了解Swing的table的renderer機制,其實無論表格有多少行,一個列是用同一個renderer實例來paint的。注意,是一個實例哈。editor也是一樣。很多初學者以為這一列用JComboBox編輯,1000行就會create成1000個ComboBox。那就完全錯了。Renderer就是一個“橡皮章”,一個章,不停的在每個格子里面“蓋章”,重繪就重新蓋;Editor就是當一個“蘿卜”,哪個“坑”需要編輯時,table動態把它“放”在這個單元格(坑)上面,下次下個單元格需要編輯,再被挪過去。對于一個列來說,就一個蘿卜,一個橡皮章。怎么會說“占用內存”?如果說1000行字符串占用內存,那這些字符串用什么語言和平臺不占用內存呢?同樣字符串在不同的語言和平臺上可以說占用內存幾乎沒什么差別。這個以后可以專門討論。

                  在這個本程序中,狀態欄上有一個封裝好的內存監控工具條:


                  它的作用是監測目前Java的總的申請的堆內存以及使用的內存。相關代碼如下:

          MemoryMXBean memorymbean = ManagementFactory.getMemoryMXBean();  

              

           
          long usedMemory = memorymbean.getHeapMemoryUsage().getUsed();  

           
          long totalMemory = memorymbean.getHeapMemoryUsage().getMax(); 

                  上面圖片中的“18M/63M”標明默認Java堆大小是64M目前使用了18M。嘗試多打開一些表格界面、拓撲圖界面,可見內存使用并不是很多。

                  說Swing的效率低,也不是很有說服力。其實Swing本質還是Java2D在paint東西,看看那些雜亂的Metal***UI源碼就知道了。不過Swing確實設計的夠復雜啰嗦,一個LnF就能繞死人。這些機制會導致Swing慢一些。不過說到底程序的快慢瓶頸還不是在Swing上,還是在如何設計和使用上。例如線程的處理等等,這些都不是初學者很容易搞定的東西。這也導致Swing總是被貼上“慢”的標簽。

                  自動布局方面,也是比較啰嗦的。如果用IDE的話,推薦NetBeans里面的GUI編輯工具,它使用的實際是Matisse這個layout。這里有兩篇官方文章介紹:
                   http://wiki.netbeans.org/UsingGUIEditor
                   http://netbeans.org/features/java/swing.html

                  如果手寫代碼,我還是推薦一個超強但比較復雜的TableLayout。這里有其介紹:
                   http://java.sun.com/products/jfc/tsc/articles/tablelayout/

                  其他簡單的布局,大多可以用Swing內置的幾個layout搞定。另外盡量多套用Panel進行嵌套,化繁為簡。不要試圖一次一個Panel+Layout把一個復雜的界面搞定,那樣會很累。

                  有朋友很不齒這里使用到了JGoodies和TWaver,這里也說明一下。在JGoodies的基礎上再去定制UI確實美觀了不少,不過理論上確實可以徹底拋開JGoodies。這樣就要完全徹底重寫一整套的LnF了,包括文本框按鈕啊所有的東西。目前確實還沒有這樣的時間和精力,以后會考慮出一個WithoutJGoodies版本。使用TWaver主要是為了做中間的流程圖和拓撲圖,并且使用的也比較順手了。如果不需要中間的拓撲圖流程圖,也可以without TWaver,以后會考慮改一版。不過這些東西都是很不錯的工具,能用就拿來為我所用,不喜歡用就借鑒一下了事。


          程序下載

                  麻煩請至我之前發表文章的TWaver中文社區下載。

                  執行方法:解壓zip文件,雙擊其中的run.bat。

                  運行環境:Java 6。

                  其他說明:zip包中的free.jar就是本文提到的框架。其他兩個jar包是jgoodies lnf和twaver做流程圖的支撐包,可不用理會。

                  下一次我會詳細介紹每一個組件的制作方法和相關代碼。

          posted on 2010-08-04 14:49 老三 閱讀(2629) 評論(0)  編輯  收藏

          導航

          公告

          一個不錯的UI技術中文社區:http://twaver.servasoft.com/
          還有一個論壇:http://twaver.servasoft.com/forum/

          常用鏈接

          隨筆檔案

          最新隨筆

          搜索

          最新評論

          主站蜘蛛池模板: 当阳市| 三江| 宝兴县| 阜平县| 涿鹿县| 甘洛县| 吴江市| 陆河县| 屏东县| 五原县| 杨浦区| 乾安县| 嵊州市| 庄河市| 阿克| 德令哈市| 工布江达县| 黔江区| 平和县| 卓资县| 历史| 太白县| 横峰县| 藁城市| 巴楚县| 太湖县| 玉龙| 尉氏县| 桓仁| 蓬莱市| 宕昌县| 泰宁县| 天水市| 太和县| 东阿县| 元阳县| 香格里拉县| 霸州市| 伊金霍洛旗| 类乌齐县| 太白县|