AbaGUIBuilder:一個(gè)適合Dephi和VB開(kāi)發(fā)者開(kāi)源GUI編譯器摘要:越來(lái)越多的應用軟件開(kāi)發(fā)者選擇Java/Swing作為開(kāi)發(fā)平臺。本文將介紹一款開(kāi)源編譯器AbaGUIBuilder,通過(guò)提供一個(gè)類(lèi)似于Visual Basic 或 Delphi的模式使開(kāi)發(fā)者輕松遷移到Java/Swing平臺。
版權聲明:任何獲得Matrix授權的網(wǎng)站,轉載時(shí)請務(wù)必保留以下作者信息和鏈接作者:Mario H Castillo;
greenieu(作者的blog:
http://blog.matrix.org.cn/page/greenieu)
原文:
http://www.javaworld.com/javaworld/jw-12-2005/jw-1219-abacus.html譯文:
http://www.matrix.org.cn/resource/article/44/44242_VB+Swing.html關(guān)鍵字:VB;Swing
當Abacus Research AG,一家商業(yè)軟件開(kāi)發(fā)公司,決定將開(kāi)發(fā)平臺從 Borland 的 Delphi 轉向Java Swing時(shí),它發(fā)現自己站在了軟件開(kāi)發(fā)的十字路口。
我們大量的應用程序開(kāi)發(fā)團隊擁有多年的Delphi GUI開(kāi)發(fā)經(jīng)驗,卻沒(méi)有任何的Java/Swing 經(jīng)驗,并且我們需要在極短的時(shí)間內將大量的Delphi應用程序轉換為Swing。在研究了當時(shí)可用的GUI工具后,我們覺(jué)得我們應該通過(guò)贊助一個(gè)GPL開(kāi)源Java GUI編譯器來(lái)達到自己的目標,而且這個(gè)編譯器還可以幫助其他的應用程序開(kāi)發(fā)者面對相同的挑戰。
AbaGUIBuilder ,Abacus Java GUI編譯器被設計用來(lái)實(shí)現輕松地從VB或Delphi開(kāi)發(fā)轉向Java Swing。這一策略幫助Abacus Research實(shí)現了其Java版應用程序的交付,縮短了開(kāi)發(fā)時(shí)間,使其開(kāi)發(fā)人員把精力投向商業(yè)應用,而不是Swing框架的錯綜復雜。
如圖1所示,AbaGUIBuilder有能夠在許多其他開(kāi)發(fā)環(huán)境如VB和Delphi找到的要素。位于視窗左上角是活動(dòng)對象樹(shù),其下是Swing組件選擇區。位于視窗的中上部是開(kāi)發(fā)面板,或者說(shuō)是“畫(huà)布”,在這里放入Swing組件將其實(shí)例化。在右上部是屬性編輯器。下部是事件面板,包括兩個(gè)制表符頁(yè),分別是事件代碼編輯器,為每個(gè)單獨的可視對象添加事件代碼,和消息面板,顯示AbaGUIBuilder的狀態(tài)消息。
圖1. Abacus GUI編譯器.
為什么做我們自己的GUI工具? 為什么我們選擇寫(xiě)自己的工具?開(kāi)始,我們決定我們的工具應該包括以下五個(gè)要求:
1. 容易使用
2. 不需要布局管理器的使用經(jīng)驗
3. 不需要Swing的使用經(jīng)驗
4. 不需要輸出Swing代碼
5. 實(shí)現商業(yè)邏輯與UI的分離
我們在評估當時(shí)可用的GUI開(kāi)發(fā)工具時(shí)發(fā)現好的IDE都是手寫(xiě)Swing代碼,這就不符合我們的第一個(gè)和最關(guān)鍵要求。
我們定義的容易使用是指任一開(kāi)發(fā)者不管他/她的Java Swing經(jīng)驗,都具有在幾分鐘而不是幾小時(shí)內開(kāi)發(fā)一個(gè)可運行的GUI表單,因此就要是開(kāi)發(fā)者的精力集中在商業(yè)邏輯上而不是框架的細節。一開(kāi)始我們的開(kāi)發(fā)者就需要所見(jiàn)即所得的環(huán)境,以便能夠真實(shí)地感知當應用程序發(fā)布的時(shí)候的情況。這一功能的實(shí)現節省了開(kāi)發(fā)者的大量時(shí)間。但當時(shí)我們評估的工具沒(méi)有一個(gè)能夠實(shí)現這個(gè)功能;設計的屏幕與輸出的屏幕并不一樣還有糟糕的調度算法,對我們來(lái)說(shuō)簡(jiǎn)直就是巨大的倒退。AbaGUIBuilder通過(guò)預覽模式來(lái)實(shí)現這一功能,你可以在開(kāi)發(fā)時(shí)看到它運行起來(lái)的樣子。
為什么Abacus Research要求UI和商業(yè)邏輯的分離?因為企業(yè)要處理不斷變換的政府規則,例如稅收和工資計算;我們需要在一個(gè)獨立的包裝模塊里維護規則和公式時(shí)保持UI不變的能力,使得當公式改變時(shí),應用程序JAR(UI)并不需要變化。因此只有改變的公式需要測試,使得發(fā)布的進(jìn)程簡(jiǎn)單化。
為了滿(mǎn)足這個(gè)需求,我們設計的GUI編譯器將應用程序和事件匯編到一個(gè)應用程序JAR,JAR隱藏了所有的GUI Swing 代碼并且通過(guò)一個(gè)renderer類(lèi)(AdaRenderer)在運行時(shí)來(lái)執行應用程序。
不需要Swing經(jīng)驗為了確保開(kāi)發(fā)工具能夠做到真正的所見(jiàn)即所得,我們決定采用類(lèi)似Delphi和VB中用XY坐標來(lái)定位的布局管理方式。采用這種方式,Swing JFrame就是一個(gè)畫(huà)布,開(kāi)發(fā)者可以將Swing組件放入JFrame的XY布局中。有了XY布局管理器,我們的開(kāi)發(fā)者不需要理解Swing中并不熟悉的,復雜的布局管理器,這樣我們的應用程序開(kāi)發(fā)者就可以把精力集中到應用程序UI和它的商業(yè)邏輯中。
事實(shí)上,AbaGUIBuilder包含了大部分的Swing可視組件,從面板到制表符頁(yè),還有對菜單﹑菜單項,帶有Java數據庫連接的數據庫感知組件,JFreeChart組件的支持,和導入第三方可視類(lèi)庫的能力。所有這些組件都可以從組件選擇區拖入一個(gè)空框架來(lái)開(kāi)發(fā)你的GUI應用程序。
示例項目: 跟蹤開(kāi)發(fā)商的聯(lián)絡(luò )信息最佳的展示AbaGUIBuilder RAD(快速應用程序開(kāi)發(fā))的方式就是開(kāi)發(fā)一個(gè)帶有菜單欄的多文本制表符面板的示例程序。首先,你必須通過(guò)在組件選擇區選擇JFrame,將其拖入應用程序畫(huà)布中來(lái)實(shí)現將JFrame對象放入空的表單面板中。然后,將所有的可視組件托在JFrame上。注意:當你開(kāi)始一個(gè)新的項目時(shí),必須先放入JFrame,使其成為你的對象畫(huà)布,見(jiàn)圖2。
圖2. 應用程序JFrame 作為畫(huà)布. 點(diǎn)擊縮略圖查看完整圖.
其次,增加一個(gè)制表符格和兩個(gè)制表符頁(yè)。在組件選擇區的容器區內選擇JTabbedPane將其拖入JFrame1。當JTabbedPane放置好后,右鍵,在彈出菜單中選擇 Add JATabPage在面板上增加兩個(gè)制表符頁(yè)。如圖3。
圖3. 增機制表符頁(yè): 右鍵制表符頁(yè)選擇Add JATabPage.
然后,在屬性欄中選擇TabTitle為每個(gè)制表符頁(yè)設置標題。
圖4.可以放入Swing組件的空制表符頁(yè).
這時(shí),你已經(jīng)有了兩個(gè)空的制表符頁(yè),你可以從組件選擇區選擇任意的Swing組件放入其中。在我們的例子中,開(kāi)發(fā)者制表符頁(yè)中包含兩個(gè)屏面,上面有一系列的JLabel和JTextField對象。你能夠很快的開(kāi)發(fā)出一個(gè)類(lèi)似圖5的應用程序。作為一個(gè)可視化應用程序開(kāi)發(fā)者,你能夠體會(huì )到使用Abacus GUI編譯器能給你開(kāi)發(fā)復雜的GUI應用程序所帶來(lái)的方便。
圖5. 短時(shí)開(kāi)發(fā)的應用程序.
編譯器帶的透視圖模式是一個(gè)很有用的特征,因為它能夠預覽運行時(shí)的應用程序。通過(guò)選擇工具欄的Run選項或者按F9鍵,即可進(jìn)入透視圖模式
圖6. 所見(jiàn)即所得: 開(kāi)發(fā)時(shí)檢查視覺(jué)效果.
這時(shí)保存你的工作,按下Ctrl-S或者選擇Save選項,給項目起名叫devteam,將其保存到示例目錄中。在你保存完項目后,打開(kāi)AbaGUIBuilder的示例目錄,打開(kāi)文件devteam.proj。proj文件是一個(gè)XML文件,其中定義了應用程序中的所有類(lèi),對象,對象的性質(zhì),甚至是代碼。這是一個(gè)對你的可視項目的表達平臺。
增加事件句柄為每個(gè)對象增加事件句柄是一個(gè)直截了當的過(guò)程。你所要做的就是點(diǎn)擊對象,從事件列表中選擇你希望中斷產(chǎn)生的事件,并為事件填寫(xiě)合適的Java代碼。再一次證明,AbaGUIBuilder的設計符合Delphi和VB的模式。我們的目標是對應用程序開(kāi)發(fā)者隱藏UI的實(shí)現,例如事件監聽(tīng)器等。舉個(gè)例子,如圖7,為了實(shí)現按下Exit(退出)按鈕時(shí),彈出一個(gè)確認對話(huà)框,首先選擇Exit按鈕的actionPerformed事件,然后填入如下Java代碼
圖7. 為可視化組件增加事件句柄.
切記,事件句柄在IDE透視圖模式下并不能使用,只有在運行時(shí)才被激活,所以你必須編譯,運行應用程序才能檢查結果。
可視化地增加一個(gè)菜單和菜單項是另一個(gè)強大的并節省時(shí)間的特征。你所要做的就是從組件選擇區選擇JMenuBar并將其放在框架的任意地方。JMenuBar一般放在頂部且XY坐標無(wú)關(guān)。然后右鍵點(diǎn)擊JMenuBar,彈出一個(gè)彈出框,如圖8。為菜單增加JMenu,JMenuItem(s),和事件句柄。
圖8. 可視化增加菜單和菜單項.
然后,復制Exit按鈕的actionPerformed事件代碼到Exit菜單項中,使得不管選擇Exit按鈕還是Exit菜單項都回彈出一樣的確認對話(huà)框。最后,點(diǎn)擊工具欄中的Save(With Compile)?,F在你完成了你的第一個(gè)AbaGUIBuilder應用程序。
代碼到哪里去了?我們經(jīng)常聽(tīng)到這樣的問(wèn)題:代碼去哪了?AbaGUIBuilder并不是不創(chuàng )造Java代碼,只不過(guò)是編譯器內部生成的Java代碼不被看到和用到而已。GUI編譯器通過(guò)運行獨立的包裝程序(renderer)將內部代碼編譯到應用程序的jar文件中。事實(shí)上,你可以在\bin\output目錄下檢測AbaGUIBuilder產(chǎn)生的Java代碼。但是切記,這些代碼并使被外部使用的;它只不過(guò)作為一個(gè)輔助工具,當編譯器生成的代碼萬(wàn)一有問(wèn)題時(shí)使用。
生成項目文件(.proj)后,GUI編譯器生成兩個(gè)文件,你的應用程序jar文件和decl文件。隨后當你寫(xiě)包裝器文件時(shí),decl文件會(huì )有幫助。它包含了所有的對象定義和一個(gè)通用入口函數getReferences(),并且它將UI表單的所有可視元素寫(xiě)為私有變量。我們可以使用decl文件程序段中的這些私有變量實(shí)現商業(yè)邏輯和UI的分離。
開(kāi)發(fā)過(guò)程中,我們推薦你使用例子文件夾中的runproz腳本來(lái)運行你的應用程序jar文件。這個(gè)腳本文件設置了classpath,填交了所有需要的JAR,使用示例Java包裝器來(lái)運行應用程序JAR。如圖9,當你運行devteam應用程序時(shí),命令如下:
runproz \abaguibuilder-1.7\samples\devteam.jar
圖9. 部署應用程序.
理解runproz的機制很重要,雖然很簡(jiǎn)單,讓我們注意下行:
"%JAVA_HOME%\bin\java.exe" exec %1
exec是示例包裝器AbaRenderer提供的默認加載機制,參數%1指的是AbaGUIBuilder應用程序JAR的名字。當JAR的路徑和名字傳給exec.java時(shí),它將加載和運行指定的應用程序JAR。這就是應用程序JAR運行的機制。
編寫(xiě)自己的包裝器AbaRenderer包裝器是一個(gè)用AbaRenderer 對象來(lái)加載應用程序jar的Java程序。包裝器是一個(gè)僅僅需要幾行代碼的簡(jiǎn)單程序。
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();}
}
}
當部署應用程序時(shí),你可以選擇使用runproz和示例包裝器來(lái)發(fā)布它,也可以使用你自己寫(xiě)的包裝器和classpath。當你需要為你的包裝器增加其它的一些特征時(shí)我們推薦你編寫(xiě)自己的包裝器,例如:使用第三方程序庫的監聽(tīng)器,手工初始化對象,為組合框增加代碼,或者最后將UI從業(yè)務(wù)邏輯中分離出來(lái)等。
將業(yè)務(wù)邏輯從UI中分離出來(lái)為了將應用程序的UI和業(yè)務(wù)邏輯分離開(kāi),你必須寫(xiě)自己的包裝器。一個(gè)分離的簡(jiǎn)單例子就是在開(kāi)發(fā)工具和項目以外,通過(guò)包裝器手工地初始化應用程序的可視組件。當你再次調用時(shí),GUI編譯器生成一個(gè)聲明文件。這個(gè)文件有一個(gè)訪(fǎng)問(wèn)方法可以初始化一系列私有變量,這些私有變量是表單上可視對象的引用。getReferences()方法允許開(kāi)發(fā)者訪(fǎng)問(wèn)和操作表單上的任一可視組件。
下面的exec2程序在第一個(gè)制表符位置初始化了一個(gè)組合框,示范了一個(gè)簡(jiǎn)單的應用程序UI和業(yè)務(wù)邏輯的分離:
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();
}
}
}
上面例子演示了一個(gè)簡(jiǎn)單、清晰的UI和業(yè)務(wù)邏輯的分離。明顯的優(yōu)勢就是你可以輕松地改變初始化例程而不需要改變應用程序UI。你將發(fā)現當你的應用程序變得越來(lái)越大,越來(lái)越復雜時(shí),這一特征越來(lái)越重要——對于所有的開(kāi)發(fā)項目而言,這將是一個(gè)值得效仿的做法。
結論AbaGUIBuilder最初是為了滿(mǎn)足我們的Delphi應用程序開(kāi)發(fā)者的需要而設計的,節省了很多開(kāi)發(fā)時(shí)間,而且是我們的GUI開(kāi)發(fā)轉換變得容易。對于其他的大多數Delphi和VB的開(kāi)發(fā)者而言,它也能做得很好。
資源·下載本文源代碼: 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
·更多關(guān)于GUI開(kāi)發(fā)的文章,請瀏覽JavaWorld文章列表的用戶(hù)界面設計部分: http://www.javaworld.com/channel_content/jw-ui-index.shtml
·