當Abacus Research AG,一家商業軟體開發公司,決定将開發平台從 Borland 的 Delphi 轉向Java Swing時,它發現自己站在了軟體開發的十字路口。
我們大量的應用程式開發團隊擁有多年的Delphi GUI開發經驗,卻沒有任何的Java/Swing 經驗,并且我們需要在極短的時間内将大量的Delphi應用程式轉換為Swing。在研究了當時可用的GUI工具後,我們覺得我們應該通過贊助一個GPL開源Java GUI編譯器來達到自己的目标,而且這個編譯器還可以幫助其他的應用程式開發者面對相同的挑戰。
AbaGUIBuilder ,Abacus Java GUI編譯器被設計用來實作輕松地從VB或Delphi開發轉向Java Swing。這一政策幫助Abacus Research實作了其Java版應用程式的傳遞,縮短了開發時間,使其開發人員把精力投向商業應用,而不是Swing架構的錯綜複雜。
如圖1所示,AbaGUIBuilder有能夠在許多其他開發環境如VB和Delphi找到的要素。位于視窗左上角是活動對象樹,其下是Swing元件選擇區。位于視窗的中上部是開發面闆,或者說是“畫布”,在這裡放入Swing元件将其執行個體化。在右上部是屬性編輯器。下部是事件面闆,包括兩個制表符頁,分别是事件代碼編輯器,為每個單獨的可視對象添加事件代碼,和消息面闆,顯示AbaGUIBuilder的狀态消息。

圖1. Abacus GUI編譯器.
為什麼做我們自己的GUI工具?
為什麼我們選擇寫自己的工具?開始,我們決定我們的工具應該包括以下五個要求:
1. 容易使用
2.不需要布局管理器的使用經驗
3. 不需要Swing的使用經驗
4. 不需要輸出Swing代碼
5. 實作商業邏輯與UI的分離
我們在評估當時可用的GUI開發工具時發現好的IDE都是手寫Swing代碼,這就不符合我們的第一個和最關鍵要求。
我們定義的容易使用是指任一開發者不管他/她的Java Swing經驗,都具有在幾分鐘而不是幾小時内開發一個可運作的GUI表單,是以就要是開發者的精力集中在商業邏輯上而不是架構的細節。一開始我們的開發者就需要所見即所得的環境,以便能夠真實地感覺當應用程式釋出的時候的情況。這一功能的實作節省了開發者的大量時間。但當時我們評估的工具沒有一個能夠實作這個功能;設計的螢幕與輸出的螢幕并不一樣還有糟糕的排程算法,對我們來說簡直就是巨大的倒退。AbaGUIBuilder通過預覽模式來實作這一功能,你可以在開發時看到它運作起來的樣子。
為什麼Abacus Research要求UI和商業邏輯的分離?因為企業要處理不斷變換的政府規則,例如稅收和工資計算;我們需要在一個獨立的包裝子產品裡維護規則和公式時保持UI不變的能力,使得當公式改變時,應用程式JAR(UI)并不需要變化。是以隻有改變的公式需要測試,使得釋出的程序簡單化。
為了滿足這個需求,我們設計的GUI編譯器将應用程式和事件彙編到一個應用程式JAR,JAR隐藏了所有的GUI Swing 代碼并且通過一個renderer類(AdaRenderer)在運作時來執行應用程式。
不需要Swing經驗
為了確定開發工具能夠做到真正的所見即所得,我們決定采用類似Delphi和VB中用XY坐标來定位的布局管理方式。采用這種方式,Swing JFrame就是一個畫布,開發者可以将Swing元件放入JFrame的XY布局中。有了XY布局管理器,我們的開發者不需要了解Swing中并不熟悉的,複雜的布局管理器,這樣我們的應用程式開發者就可以把精力集中到應用程式UI和它的商業邏輯中。
事實上,AbaGUIBuilder包含了大部分的Swing可視元件,從面闆到制表符頁,還有對菜單﹑菜單項,帶有Java資料庫連接配接的資料庫感覺元件,JFreeChart元件的支援,和導入第三方可視類庫的能力。所有這些元件都可以從元件選擇區拖入一個空架構來開發你的GUI應用程式。
示例項目: 跟蹤開發商的聯絡資訊
最佳的展示AbaGUIBuilder RAD(快速應用程式開發)的方式就是開發一個帶有菜單欄的多文本制表符面闆的示例程式。首先,你必須通過在元件選擇區選擇JFrame,将其拖入應用程式畫布中來實作将JFrame對象放入空的表單面闆中。然後,将所有的可視元件托在JFrame上。注意:當你開始一個新的項目時,必須先放入JFrame,使其成為你的對象畫布,見圖2。
圖2. 應用程式JFrame 作為畫布. 點選縮略圖檢視完整圖.
其次,增加一個制表符格和兩個制表符頁。在元件選擇區的容器區内選擇JTabbedPane将其拖入JFrame1。當JTabbedPane放置好後,右鍵,在彈出菜單中選擇 Add JATabPage在面闆上增加兩個制表符頁。如圖3。
圖3. 增機制表符頁: 右鍵制表符頁選擇Add JATabPage.
然後,在屬性欄中選擇TabTitle為每個制表符頁設定标題。
圖4.可以放入Swing元件的空制表符頁.
這時,你已經有了兩個空的制表符頁,你可以從元件選擇區選擇任意的Swing元件放入其中。在我們的例子中,開發者制表符頁中包含兩個屏面,上面有一系列的JLabel和JTextField對象。你能夠很快的開發出一個類似圖5的應用程式。作為一個可視化應用程式開發者,你能夠體會到使用Abacus GUI編譯器能給你開發複雜的GUI應用程式所帶來的友善。
圖5. 短時開發的應用程式.
編譯器帶的透視圖模式是一個很有用的特征,因為它能夠預覽運作時的應用程式。通過選擇工具欄的Run選項或者按F9鍵,即可進入透視圖模式
圖6. 所見即所得: 開發時檢查視覺效果.
這時儲存你的工作,按下Ctrl-S或者選擇Save選項,給項目起名叫devteam,将其儲存到示例目錄中。在你儲存完項目後,打開AbaGUIBuilder的示例目錄,打開檔案devteam.proj。proj檔案是一個XML檔案,其中定義了應用程式中的所有類,對象,對象的性質,甚至是代碼。這是一個對你的可視項目的表達平台。
增加事件句柄
為每個對象增加事件句柄是一個直截了當的過程。你所要做的就是點選對象,從事件清單中選擇你希望中斷産生的事件,并為事件填寫合适的Java代碼。再一次證明,AbaGUIBuilder的設計符合Delphi和VB的模式。我們的目标是對應用程式開發者隐藏UI的實作,例如事件監聽器等。舉個例子,如圖7,為了實作按下Exit(退出)按鈕時,彈出一個确認對話框,首先選擇Exit按鈕的actionPerformed事件,然後填入如下Java代碼
圖7. 為可視化元件增加事件句柄.
切記,事件句柄在IDE透視圖模式下并不能使用,隻有在運作時才被激活,是以你必須編譯,運作應用程式才能檢查結果。
可視化地增加一個菜單和菜單項是另一個強大的并節省時間的特征。你所要做的就是從元件選擇區選擇JMenuBar并将其放在架構的任意地方。JMenuBar一般放在頂部且XY坐标無關。然後右鍵點選JMenuBar,彈出一個彈出框,如圖8。為菜單增加JMenu,JMenuItem(s),和事件句柄。
圖8. 可視化增加菜單和菜單項.
然後,複制Exit按鈕的actionPerformed事件代碼到Exit菜單項中,使得不管選擇Exit按鈕還是Exit菜單項都回彈出一樣的确認對話框。最後,點選工具欄中的Save(With Compile)。現在你完成了你的第一個AbaGUIBuilder應用程式。
代碼到哪裡去了?
我們經常聽到這樣的問題:代碼去哪了?AbaGUIBuilder并不是不創造Java代碼,隻不過是編譯器内部生成的Java代碼不被看到和用到而已。GUI編譯器通過運作獨立的包裝程式(renderer)将内部代碼編譯到應用程式的jar檔案中。事實上,你可以在/bin/output目錄下檢測AbaGUIBuilder産生的Java代碼。但是切記,這些代碼并使被外部使用的;它隻不過作為一個輔助工具,當編譯器生成的代碼萬一有問題時使用。
生成項目檔案(.proj)後,GUI編譯器生成兩個檔案,你的應用程式jar檔案和decl檔案。随後當你寫包裝器檔案時,decl檔案會有幫助。它包含了所有的對象定義和一個通用入口函數getReferences(),并且它将UI表單的所有可視元素寫為私有變量。我們可以使用decl檔案程式段中的這些私有變量實作商業邏輯和UI的分離。
開發過程中,我們推薦你使用例子檔案夾中的runproz腳本來運作你的應用程式jar檔案。這個腳本檔案設定了classpath,填交了所有需要的JAR,使用示例Java包裝器來運作應用程式JAR。如圖9,當你運作devteam應用程式時,指令如下:runproz /abaguibuilder-1.7/samples/devteam.jar
圖9. 部署應用程式.
了解runproz的機制很重要,雖然很簡單,讓我們注意下行:"%JAVA_HOME%/bin/java.exe" exec %1
exec是示例包裝器AbaRenderer提供的預設加載機制,參數%1指的是AbaGUIBuilder應用程式JAR的名字。當JAR的路徑和名字傳給exec.java時,它将加載和運作指定的應用程式JAR。這就是應用程式JAR運作的機制。
編寫自己的包裝器
AbaRenderer包裝器是一個用AbaRenderer 對象來加載應用程式jar的Java程式。包裝器是一個僅僅需要幾行代碼的簡單程式。
public class exec
{
public static AbaRenderer m_AbaRenderer ;
// Assignments for this user interface
public static void main(String[] args)
{
String docname = new String(args[0]);
try
{
System.out.println("Loading.." + docname);
m_AbaRenderer = new AbaRenderer(docname, true , null);
boolean bTestLoad = m_AbaRenderer.load();
if(bTestLoad)
m_AbaRenderer.renderInterface(); }
catch(Exception e)
{e.printStackTrace();}
}
}
當部署應用程式時,你可以選擇使用runproz和示例包裝器來釋出它,也可以使用你自己寫的包裝器和classpath。當你需要為你的包裝器增加其它的一些特征時我們推薦你編寫自己的包裝器,例如:使用第三方程式庫的監聽器,手工初始化對象,為組合框增加代碼,或者最後将UI從業務邏輯中分離出來等。
将業務邏輯從UI中分離出來
為了将應用程式的UI和業務邏輯分離開,你必須寫自己的包裝器。一個分離的簡單例子就是在開發工具和項目以外,通過包裝器手工地初始化應用程式的可視元件。當你再次調用時,GUI編譯器生成一個聲明檔案。這個檔案有一個通路方法可以初始化一系列私有變量,這些私有變量是表單上可視對象的引用。getReferences()方法允許開發者通路和操作表單上的任一可視元件。
下面的exec2程式在第一個制表符位置初始化了一個組合框,示範了一個簡單的應用程式UI和業務邏輯的分離:
public class exec2
{
public static AbaRenderer m_AbaRenderer ;
// Declarations of variables for this user interface.
…….
private JComboBox JStComboBox;
// Assignments for this user interface
public void getReferences()
{
…..
//Loads the visual object JComboBox1 to private data JComboBox1
JStComboBox= (JComboBox)m_AbaRenderer.getObject("JComboBox1");
…..
}
// Assignments for this user interface
public static void main(String[] args)
{
String docname = new String(args[0]);
try
{
System.out.println("Loading.." + docname);
m_AbaRenderer = new AbaRenderer(docname, true , null);
boolean bTestLoad = m_AbaRenderer.load();
if(bTestLoad)
{
m_AbaRenderer.renderInterface();
getReferences();
// Sample access to objects
JStComboBox.addItem("FL");
JStComboBox.addItem("CA");
JStComboBox.addItem("WA");
JStComboBox.addItem("MD");
JStComboBox.addItem("PA");
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
上面例子示範了一個簡單、清晰的UI和業務邏輯的分離。明顯的優勢就是你可以輕松地改變初始化例程而不需要改變應用程式UI。你将發現當你的應用程式變得越來越大,越來越複雜時,這一特征越來越重要——對于所有的開發項目而言,這将是一個值得效仿的做法。
結論
AbaGUIBuilder最初是為了滿足我們的Delphi應用程式開發者的需要而設計的,節省了很多開發時間,而且是我們的GUI開發轉換變得容易。對于其他的大多數Delphi和VB的開發者而言,它也能做得很好。
資源
·下載下傳本文源代碼: http://www.javaworld.com/javaworld/jw-12-2005/abacus/jw-1219-abacus.zip
·下載下傳AbaGUIBuilder: http://sourceforge.net/projects/abaguibuilder
·Screen shots和其他文章: http://www.openabacus.org
·Abacus 研究: http://www.abacus.ch
·更多關于GUI開發的文章,請浏覽JavaWorld文章清單的使用者界面設計部分: http://www.javaworld.com/channel_content/jw-ui-index.shtml
·GUI程式設計論壇:http://www.matrix.org.cn/topic.shtml?forumId=49
版權聲明:任何獲得Matrix授權的網站,轉載時請務必保留以下作者資訊和連結
原文:http://www.javaworld.com/
譯文:http://www.matrix.org.cn/