日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

用 TableModel Free 框架简化 Swing 开发——JTable

發布時間:2023/12/14 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用 TableModel Free 框架简化 Swing 开发——JTable 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

用 TableModel Free 框架簡化 Swing 開發

從 TableModel 的負擔中解脫出來

Michael Abernethy, 軟件工程師 II, EMC

簡介:?本文將介紹 TableModel Free(TMF) 框架,該框架利用 SWing JTable 消除了對 TableModel 的需要。通過將所有特定于表的數據移到編譯好的代碼之外,并將它們放在可配置的 XML 文件中,TMF 框架使 JTable 具備了更強的可配置性。框架開發人員和 Java UI 的熱心支持者 Michael Abernethy 將帶您遍歷整個 TMF 框架,幫助您把 TableModel 的大小從數百行代碼減少到只有區區一行代碼,把管理工作變成小菜一碟。

標記本文!

發布日期:?2004 年 10 月 12 日?
級別:?初級?
訪問情況 :?2606 次瀏覽?
評論:?0?(查看?|?添加評論?- 登錄)

?平均分 (4個評分)
為本文評分

“Java? Desktop 的再介紹”強調了今年的 JavaOne 大會。對于那些抱怨 Swing 太慢、太難使用、界面太難看的開發人員來說,Swing 和 GUI 開發所做的更新努力,并沒有帶來什么受人歡迎的好消息。如果您最近沒有用過 Swing,那么您會很高興聽到其中的許多問題已經得到解決。Swing 被重新設計,它能執行得更好,并能更好地利用 Java 2D API。Swing 的開發者在 1.4 版甚至最新發布的 5.0 版中提高了外觀支持。Swing 從沒像現在這么好過。

Swing 社區現在需要的是能夠讓 GUI 開發變成一個更加順利、更加容易的過程的工具。而這正是本文的目標所在。

本文將介紹 TableModel Free(TMF)框架,這是一個 GUI 開發包,它解除了為每個 JTable 建立 TableModel 的需要(在這篇文章中,我將 TableModel 稱為?傳統 TableModel,以便將它們與我為該框架引入的新結構區分開來);在處理過程中,能夠使您的 JTable 具備更高的可配置性和可維護性。

如果以前曾經用過 JTable,那么您可能也同時被迫使用了 TableModel。您可能還注意到,每個 TableModel 中的所有代碼,與其他 TableModel 中的代碼幾乎是一樣的,在編譯的 Java 類中,有差異的代碼實際上是不存在的。本文將分析 TableModel/JTable 目前的設計方法,說明這種設計的不足,展示為什么它沒有實現模型-視圖-控制器(MVC)模式的真正目標。您將看到框架和構成 TMF 框架的代碼 —— 我以前編寫的代碼與最常用的開放源代碼項目的組合。使用該框架,開發人員可以把 TableModel 的大小從數百行代碼減少到只有區區一行,并把重要的表信息放在外部 XML 文件中。在讀完本文之后,只使用如下所示的一行代碼,您就可以管理您的 JTable 數據:

TableUtilities.setViewToModel("tableconfig.xml", "My Table", myJTable, CollectionUtilities.observableList(myData));

TMF 框架中的開放源代碼包

讓我們簡要了解一下我用來協助構建 TMF 框架的兩個開放源代碼包。通過組合開放源代碼包,并加入一些創新,您可以開發出非常強大的程序。請參閱?參考資料中這些代碼包的鏈接。

Apache Jakarta Commons Collections?
最知名也最常用的開放源代碼項目,可能就是 Apache 保護下的那些項目。Apache Jakarta 項目包含許多特定于 Java 的擴展和包,其中之一就是 Commons 項目。它的目標,正如在 Web 站點上所說那樣,是“建立并維護可重用的 Java 組件”。其中列出了太多組件,而本文使用的只是 Jakarta Commons Collections 框架,它提供了大量對 Java Collections 框架的擴展。

Castor?
Castor 是一個被廣泛采用的 XML 解析工具,雖然已經有了許多 XML 解析器,但是 Castor 的強大使得它非常流行。使用 Castor,可以非常容易地在簡單的 XML 文檔中建立復雜的 Java 對象。它把從 XML 到 Java 對象的許多繁重的轉換工作從 XML 文件中提出取來,把復雜的轉換工作放到一個映射文件中,該映射文件充當著 Java 與 XML 的中介。由于有一些非常能干的開發人員處理了映射文件,所以即使是最困難的轉換,也可以在 XML 中進行,XML 文件非常便于閱讀和更新。所以,Castor 工具在解析用作配置文件的 XML 文件(由最終用戶更新,所以必須易于閱讀)時,最為強大。

JTable 和 TableModel 存在的 MVC 問題

MVC 已經成為非常流行的 UI 設計模式,因為它把業務邏輯清晰地從數據的視圖中分離了出來。Struts 是 MVC 在 Web 上應用的一個非常好的例子。最初,Swing 最大的一個賣點是它采用了 MVC,將視圖從模型中分離了出來,代碼背后的想法是:代碼的模塊化程度足夠高,所以,不用修改模型中的任何代碼,就可以分離出視圖。我想,任何用過 JTables 和 TableModels 的人都會發笑,告訴您這是絕對不可能的。使用 MVC 設計模式的理想情況是,在開發人員用 JList 或 JComboBox 替換 JTable 時,可以不用修改表示數據的模式中的代碼。但是,在 Swing 中做不到這點。Swing 使得把 JTable、 JList 和 JComboBox 熱交換到應用程序中成為不可能,即使所有這三個組件都是用來為相同的數據模型提供視圖。對于 Swing 中的 MVC 設計,這是一個嚴重的不足。如果您想為 JTable 交換 JList,就必須重寫視圖背后的全部代碼,才能實現該交換。

JTable/TableModel 的另一個 MVC 缺陷是:模型變化的時候,視圖不會更新自身。開發人員必須保持對模型的引用,并調用一個函數,這樣模型才會告訴視圖對自身進行更新;但是,理想的情況應當是:不需要任何額外的代碼,就能實現自動更新。

最后,JTable 和 TableModel 組件設計的問題是,它們彼此之間纏雜得過于密切。如果您修改了 JTable 中的代碼,那么您需要確保您沒有破壞負責處理的 TableModel,反之亦然。對于一個被認為是在模塊化基礎上建立的設計模式來說,目前的實現顯然是一種存在過多依賴關系的設計。

TMF 框架更好地遵循了 MVC 的目標,它把 JTable 中視圖和模型的工作更加清晰地分離開來。雖然它還沒有達到讓組件能夠熱切換的更高目標,但是它已經在正確方向上邁出了一步。

框架簡介

讓我們來檢視 TMF 框架,看看它是如何讓傳統 TableModel 過時的。設計該框架的第一部分是學習 JTable 的使用 —— 開發人員如何使用它,它顯示了什么內容,以便了理解哪些東西可以內化、通用化,哪些應當保留可配置狀態,以便開發人員配置。對于 TableModel,也要進行同樣的思考,我必須確定哪些東西可以從代碼中移出,哪些必須留在代碼中。一旦找出這些問題,接下來要做的就是確定能夠讓代碼足夠通用的最佳技術,以便所有人都能使用它,但是,還要讓代碼具備足夠的可配置性,這也是為了讓每個人都能使用它。

該框架分成三個基本部分:一個能夠處理任何類型數據的通用 TableModel、一個外部 XML 文件(負責對不同表中不同的表內容進行配置),以及模型與視圖之間的橋。

請單擊?Code圖標(或者參閱?下載部分),下載在本文中討論的源代碼、第三方 JAR 文件和 Javadoc。在本文中,您可以在 src 文件夾中找到文中介紹的所有源代碼。特定于 TMF 的代碼位于?com.ibm.j2x.swing.table?包中。

com.ibm.j2x.swing.table.BeanTableModel

BeanTableModel 是框架的第一部分。它充當的是通用 TableModel ,您可以用它來處理任何類型的數據。我知道,您可能會說,“您怎么這么肯定它適用于所有的數據呢?”確實,很明顯,我不能這么肯定,而且實際上,我確信有一些它不適用的例子。但是從我使用 JTables 的經驗來說,我愿意打賭(即使看起來我有點抬杠),實際使用中的 JTables,99% 都是用來顯示數據對象列表(也就是說,JavaBeans 組件的 ArrayList)。基于這個假設,我建立了一個通用表模型,它可以顯示任何數據對象列表,它就是BeanTableModel。

BeanTableModel 大量使用了 Java 的內省機制,來檢查 bean 中的字段,顯示正確的數據。它還使用了來自 Jakarta Commons Collections 框架(請參閱?側欄,以了解更多信息)的兩個類來輔助設計。

在我深入研究代碼之前,請讓我解釋來自類的幾個概念。因為我可以在 bean 上使用內省機制,所以我需要了解 bean 本身的信息,主要是了解字段的名稱是什么。我可以通過普通的內省機制來完成這項工作:我可以檢查 bean ,找出其字段。但是,對于表來說,這還不夠好,因為多數開發人員想讓他們的表按照指定順序顯示字段。除此之外,還有一項表需要的信息,我無法通過內省機制從 bean 中獲得,即列名消息。所以,為了獲得正確顯示,對于表中的每個列,您需要兩條信息:列名和將要顯示的 bean 中的字段。我用鍵-值對的格式表示該信息,其中,將列名用作鍵,字段作為值。

正因為如此,我在這里使用了來自 Collections 框架的適合這項工作的兩個類。?BeanMap?用作實用工具類,負責處理內省機制,它接手了內省機制的所有繁瑣工作。普通的內省機制開發需要大量的?try?/?catch?塊,對于表來說,這是沒有必要的。?BeanMap?把 bean 作為輸入,像處理 HashMap 那樣來處理它,在這里,鍵是 bean 中的字段(例如,?firstName?),值是 get 方法(例如,getFirstName()?)的結果。BeanTableModel 廣泛地運用?BeanMap?,消除了操作內省機制的麻煩,也使得訪問 bean 中的信息更加容易。

LinkedMap?是另外一個在 BeanTableModel 中全面應用的類。我們還是回到為列名-字段映射所進行的鍵-值數據設置,對于數據對象來說,很明顯應當選擇 HashMap。但是,HashPap 沒有保留插入的順序,對于表來說,這是非常重要的一部分,開發人員希望在每次顯示表的時候,都能以指定的順序顯示列。這樣,插入的順序就必須保留。解決方案是?LinkedMap?,它是?LinkedList?與?HashMap的組合,它既保留了列,也保留了列的順序信息。參見清單 1,可以查看我是如何用?LinkedMap?和?BeanMap?來設置表的信息的。


清單1. 用 LinkedMap 和 BeanMap 設置表信息
protected List mapValues = new ArrayList();protected LinkedMap columnInfo = new LinkedMap(); protected void initializeValues(Collection values){List listValues = new ArrayList(values);mapValues.clear();for (Iterator i=listValues.iterator(); i.hasNext();){mapValues.add(new BeanMap(i.next()));}}

在 BeanTableModel 中比較有趣的檢查代碼實際上是通用 TableModel 的那一部分,這部分代碼擴展了?AbstractTableModel?。將清單 2 中的代碼與您通常用來建立傳統 TableModel 的代碼進行比較,您可以看到一些類似之處。


清單 2. BeanTableModel 中的通用 TableModel 代碼?
/*** Returns the number of BeanMaps, therefore the number of JavaBeans*/ public int getRowCount() {return mapValues.size();}/*** Returns the number of key-value pairings in the column LinkedMap*/ public int getColumnCount() {return columnInfo.size();}/*** Gets the key from the LinkedMap at the specified index (and a * good example of why a LinkedMap is needed instead of a HashMap)*/ public String getColumnName(int col) {return columnInfo.get(col).toString();}/*** Gets the class of the column. A lot of developers wonder what * this is even used for. It is used by the JTable to use custom * cell renderers, some of which are built into JTables already * (Boolean, Integer, String for example). If you write a custom cell * renderer it would get loaded by the JTable for use in display if that * specified class were returned here.* The function uses the BeanMap to get the actual value out of the * JavaBean and determine its class. However, because the BeanMap * autoboxes things -- it converts the primitives to Objects for you * (e.g. ints to Integers) -- the code needs to unautobox it, since the * function must return a Class Object. Thus, it recognizes any primitives * and converts them to their respective Object class.*/ public Class getColumnClass(int col) {BeanMap map = (BeanMap)mapValues.get(0);Class c = map.getType(columnInfo.getValue(col).toString());if (c == null)return Object.class;else if (c.isPrimitive())return ClassUtilities.convertPrimitiveToObject(c);elsereturn c;}/*** The BeanTableModel automatically returns false, and if you * need to make an editable table, you'll have to subclass * BeanTableModel and override this function.*/ public boolean isCellEditable(int row, int col) {return false;}/*** The function that returns the value that you see in the JTable. It gets * the BeanMap wrapping the JavaBean based on the row, it uses the * column number to get the field from the column information LinkedMap, * and then uses the field to retrieve the value out of the BeanMap. */public Object getValueAt(int row, int col) {BeanMap map = (BeanMap)mapValues.get(row);return map.get(columnInfo.getValue(col));}/*** The opposite function of the getValueAt -- it duplicates the work of the * getValueAt, but instead puts the Object value into the BeanMap instead * of retrieving its value.*/public void setValueAt(Object value, int row, int col) {BeanMap map = (BeanMap)mapValues.get(row);map.put(columnInfo.getValue(col), value);super.fireTableRowsUpdated(row, row);}/*** The BeanTableModel implements the CollectionListener interface * (1 of the 3 parts of the framework) and thus listens for changes in the * data it is modeling and automatically updates the JTable and the * model when a change occurs to the data.*/ public void collectionChanged(CollectionEvent e){initializeValues((Collection)e.getSource());super.fireTableDataChanged();}

正如您所看到的,BeanTableModel 的整個 TableModel 足夠通用化,可以在任何表中使用。它充分利用了內省機制,省去了所有特定于 bean 的編碼工作,在傳統的 TableModel 中,這類編碼工作絕對是必需的 —— 同時也是完全冗余的。BeanTableModel 還可以在 TMF 框架之外使用,雖然在外面使用會喪失一些威力和靈活性。

看過這段代碼之后,您會提出兩個問題。首先,BeanTableModel 從哪里獲得列名-字段與鍵-值配對的信息?第二,到底什么是ObservableCollection??這些問題會將我們引入框架的接下來的兩個部分。這些問題的答案以及更多的內容,將在本文后面接下來的章節中出現。

Castor XML 解析器

保存必需的列名-字段信息的最合理的位置位于 Java 類之外,這樣,不需要再重新編譯 Java 代碼,就可以修改這個信息。因為關于列名和字段的信息是 TMF 框架中惟一明確與表有關的信息,這意味著整個表格都可以在外部進行配置。

顯然,該解決方案會自然而然把 XML 作為配置文件的語言選擇。配置文件必須為多種表模型保存信息;您還需要能夠用這個文件指定每個列中的數據。配置文件還應當盡可能地易于閱讀,因為開發人員之外的人員有可能要修改它。

這些問題的最佳解決方案是 Castor XML 解析器(有關的更多信息,請參閱?側欄)。查看 Castor 實際使用的最佳方法就是查看如何在框架中使用它。

讓我們來考慮一下配置文件的目的:保存表模型和表中列的信息。 XML 文件應當盡可能簡單地顯示這些信息。TMF 框架中的 XML 文件用清單 3 所示的格式來保存表模型信息。


清單3. TMF 配置文件示例
<model><className>demo.hr.TableModelFreeExample</className><name>Hire</name><column><name>First Name</name><field>firstName</field></column><column><name>Last Name</name><field>lastName</field></column></model>

與這個目的相反的目標是,開發人員必須處理的 Java 對象應當像 XML 文件一樣容易理解。通過 Castor XML 解析器用來存儲列信息的三個 Java 對象,就可以看到這一點,這三個對象是:?TableData?(存儲文件中的所有表模型)、?TableModelData?(存儲特定于表模型的信息)和?TableModelColumnData?(存儲列信息)。這三個類提供了 Java 開發人員所需的所有包裝器,以便得到有關 TableModel 的所有必要信息。

將所有這些包裝在一起所缺少的一個環節就是?映射文件,它是一個 XML 文件,Castor 用它把簡單的 XML 映射到簡單的 Java 對象中。在完美的世界中,映射文件也應當很簡單,但事實要比這復雜得多。良好的映射文件要使別的一切東西都保持簡單;所以一般來說,映射文件越復雜,配置文件和 Java 對象就越容易處理。映射文件所做的工作顧名思義就是把 XML 對象映射到 Java 對象。清單 4 顯示了 TMF 框架使用的映射文件。


清單 4. TMF 框架使用的 Castor 映射文件
<?xml version="1.0"?><mapping><description>A mapping file for externalized table models</description><class name="com.ibm.j2x.swing.table.TableData"><map-to xml="data"/><field name="tableModelData" collection="arraylist" type="com.ibm.j2x.swing.table.TableModelData"><bind-xml name="tableModelData"/></field></class><class name="com.ibm.j2x.swing.table.TableModelData"><map-to xml="model"/><field name="className" type="string"><bind-xml name="className"/></field><field name="name" type="string"><bind-xml name="name"/></field><field name="columns" collection="arraylist" type="com.ibm.j2x.swing.table.TableModelColumnData"><bind-xml name="columns"/></field></class><class name="com.ibm.j2x.swing.table.TableModelColumnData"><map-to xml="column"/><field name="name" type="string"><bind-xml name="name"/></field><field name="field" type="string"><bind-xml name="field"/></field> </class></mapping>

僅僅通過觀察這段代碼,您就可以看出,映射文件清晰地勾劃出了每個用來存儲表模型信息的類,定義了類的類型,并將 XML 文件中的名稱連接到了 Java 對象中的字段。請保持相同的名稱,這樣會讓事情簡單、更好管理一些,但是沒必要保持名稱相同。從?參考資料中,可以了解有關 Castor XML 映射的更多信息。

到現在為止,列名和字段信息都已外部化,可以讀入包含列信息的 Java 對象中,并且可以很容易地把信息發送給 BeanTableModel,并用它來設置列。

ObservableCollection

TMF 框架的最后一個關鍵部分,就是?ObservableCollection?。您們當中的某些人可能熟悉?ObservableCollection?的概念,它是 Java Collections 框架的一個成員,在被修改的時候,它會拋出事件,從而允許其偵聽器根據這些事件執行操作。雖然從來沒有將它引入 Java 語言的正式發行版中,但在 Internet 上,這個概念已經有了一些第三方實現。就本文而言,我使用了自己的ObservableCollection?實現,因為框架只需要一些最基本的功能。我的實現使用了一個稱為?collectionChanged()?的方法,每次發生修改時,?ObservableCollection?都會在自己的偵聽器上調用該方法。也可以將該用法稱為 Collection 類的?Decorator(有關 Collections 的 Decorator 更多信息,請參閱 Collections 框架的站點),只需要增加幾行代碼,您就可以在普通的 Collection 類中創建 Collection 類的 Observable 實例。 清單 5 顯示了 ObservableCollection 用法的示例。(這只是一個示例,沒有包含在 j2x.zip 中。)


清單 5. ObservableCollection 用法示例
// convert a normal list to an ObservableListObservableList oList = CollectionUtilities.observableList(list);// A listener could then register for events from this list by callingoList.addCollectionListener(this);// trigger event oList.add(new Integer(3));// listener receives eventpublic void collectionChanged(CollectionEvent e){// event received here}

ObservableCollection?有許多 TMF 框架之外的應用程序。如果您決定采用 TMF 框架,您會發現,在開發代碼期間,ObservableCollection?框架有許多實際的用途。

但是,它在 TMF 框架中的用途,重點在于它能更好地定義視圖和模型之間的關系,當數據發生變化時,可以自動更新視圖。您可以回想一下,這正是傳統 TableModel 的最大限制,因為每當數據發生變化時,都必須用表模型的引用來更新視圖。而在 TMF 框架中使用 ObservableCollection 時,當數據發生變化時,視圖會自動更新,不需要維護一個到模型的引用。在 BeanTableModel 的collectionChanged()?方法的實現中,您可以看到這一點。

TableUtilities

在該框架中執行的最后一步操作,是將所有內容集成到一些實用方法中,讓 TMF 框架使用起來簡單明了。這些實用方法可以在com.ibm.j2x.swing.table.TableUtilities?類中找到,該類提供了您將需要的所有輔助函數:

  • getColumnInfo()?:該實用方法用 Castor XML 文件解析指定的文件,并返回指定表模型的所有列信息,返回的形式是 BeanTableModel 所需的?LinkedMap?。當開發人員選擇從 BeanTableModel 中派生子類時,這個方法很重要。?

  • getTableModel()?:該實用方法是建立在上面的?getColumnInfo()?方法之上,它獲得列的信息,然后把信息傳遞給 BeanTableModel,返回已經設置好所有信息的 BeanTableModel。?

  • setViewToModel()?:該實用方法是最重要的函數,也是 TMF 框架的主要吸引人的地方。它也是建立在?getTableModel()?方法之上,也有一個到 JTable 的引用(JTable 中有這個表的模型),以及一個到數據(要在表中顯示)的引用。它對 JTable 上的 TableModel 進行設置,并把數據傳遞給 TableModel,結果是:只需一行代碼,就為 JTable 完成了 TableModel 的設置。TMF 框架在該方法上得到了最佳印證,TableModel 將永遠地被下面這個簡單的方法所代替:?

    TableUtilities.setViewToModel("table_config.xml", "Table", myJTable, myList);

TMF 框架實戰

每篇關于 GUI 編程的文章都需要一個示例,本文當然也不例外。該示例的目的是指出使用 TMF 框架代替傳統 TableModel 設計的主要優勢所在。示例中的應用程序將在屏幕上顯示多個表,并且可以添加或刪除表,表中可以包含不同類型的信息(?String?類型、?int類型、?Boolean?類型和?BigDecimal?類型),而且最重要的是,其中還包含可配置的列信息,必須定期更改它們。

示例應用程序的代碼從?J2X?包中分離了出來,您可以 HR 文件夾的 src 目錄中找到源代碼。還可以雙擊 build/lib 文件中編譯好的 JAR 文件,通過 JRE 運行應用程序。

在示例應用程序中,有兩個類可以相互交換,一個叫作?TableModelFreeExample?,另一個叫作?TableModelExample?。這兩個類在應用程序中做的是同樣的事,使應用程序產生的行為也相同。但是,它們的設計不同,一個使用的是 TMF 框架,另外一個則使用傳統的 TableModel。您從它們身上注意到的第一件事可能是 TMF 類?TableModelFreeExample?,該類由 63 行代碼構成,而在傳統 TableModel 版本?TableModelExample?中,它長達 285 行。

Evil HR Director 應用程序

我要使用的示例應用程序是 Evil HR Director 應用程序,它允許人力資源總監(可能很可怕,戴著眼鏡)在 JTable 中查看潛在雇員的列表,然后從表中選出雇傭的人。新雇傭的員工的資料會轉移到當前雇員使用的兩個 JTable 中;其中一個表包含個人信息,另外一個表包含財務信息。在當前雇員表中,總監可以隨意選擇解雇誰。您可以在圖 1 中看到該應用程序的 UI。


圖 1. Evil HR Director 應用程序
?

為了進一步證明 TMF 框架的簡單性,請看清單 6。這個清單只包含三行必需的代碼,就可以創建 Evil HR Director 應用程序中包含的三個表的模型。這些代碼可以在?TableModelFreeExample?中找到。


清單 6.在 Evil HR Director 應用程序中創建模型所需要的代碼
TableUtilities.setViewToModel("demo/hr/resources/evil_hr_table.xml", "Hire", hireTable, candidates); TableUtilities.setViewToModel("demo/hr/resources/evil_hr_table.xml", "Personal", personalTable, employees);TableUtilities.setViewToModel("demo/hr/resources/evil_hr_table.xml", "Financial", financialTable, employees);

為了進行比較,?TableModelExample?中包含用傳統 TableModel 方法為三個表格創建模型所需要的代碼。請查看示例包中的代碼。不過,我不想在這里列出所有代碼,因為它足足有 205 行!

演示 TMF 框架的靈活性

TMF 框架的巨大優勢之一,是它能更加容易地基于 JTable 的應用程序在其發布之后進行修改。為了證實這一點,讓我們來看兩個可能的場景,這兩個場景在使用 Evil HR Director 應用程序中每天都可能出現。在每個場景中,您都會看到框架是如何讓應用程序更加容易地適應不斷變化的用戶需求。

場景 1:公司的策略發生變化,規定在公司的應用程序中查看私人的婚姻信息是非法的。

  • TMF:最終用戶需要從 XML 配置文件中刪除?<name>Married?</name><field>married</field>?。?

  • 傳統 TableModel:開發人員必須深入研究 Java 代碼,修改?getColumnName()?,讓它無法返回列名“Married?”;修改getColumnCount()?,讓它返回的結果比以前返回的結果少一列;修改?getValueAt()?,不讓它返回?isMarried()?。然后開發人員必須重新編譯 Java 代碼,并重新部署應用程序。

場景 2:公司策略發生變化,公司覺得有必要在潛在雇員表中包含居住地所在的州的信息。

  • TMF:: 最終用戶需要將?<name>State</name><field>state</field>?添加到 XML 配置文件中。?

  • 傳統 TableModel:開發人員必須深入研究 Java 代碼,修改?getColumnName()?,添加一個叫作 “State” 新列;修改getColumnCount()?,讓它返回的列數加 1 ;修改?getValueAt()?,讓它返回?getState()?。然后開發人員必須重新編譯 Java 代碼,并重新部署應用程序。

您可以看到,當應用程序中的表發生變化時(尤其在碰到一個總是朝令夕改的老板時,更改更加頻繁),編輯 XML 文件要比重新部署整個應用程序容易得多。

使用代碼

在您飛奔過去刪除所有 TableModel 代碼之前,我想我還得占用您一分鐘解釋一下 j2x.zip 文件的內容,以及您怎樣才能在您自己的項目中使用它。(請記住,特定于 TMF 的代碼可以在?com.ibm.j2x.swing.table?包中找到;您還會在 J2X 包中找到我在以前的文章“Go state-of-the-art with IFrame.”中介紹的其他代碼,請參閱?參考資料,其中有這篇文章的鏈接。)

j2x.zip 文件包含兩上文件夾:

  • src—— 包含本文中使用的源代碼。在 src 文件夾中,還有兩個文件夾:一個是 HR,包含構成 Evil HR Director 應用程序的源代碼;另一個是 J2X,包含 J2X 項目中使用的所有源代碼。?

  • build—— 包含 Evil HR Director 應用程序和 J2X 項目編譯后的類文件。該文件夾中的 lib 文件夾則包含 HR 應用程序和 J2X 項目的 JAR 文件。

lib.zip 文件包含以下文件夾:

  • lib—— 包含所有的第三方 JAR 文件,運行應用程序或者任何使用 J2X 項目的項目,需要使用這些文件。在這個文件夾中,您還會找到第三方項目的許可。

docs.zip 文件包含下列文件夾:

  • docs—— 包含 J2X 項目的所有 JavaDoc 信息。

要在應用程序中使用 J2X 包,則需要把?CLASSPATH?指向 build/lib 文件夾中的 j2x.jar 以及 lib 文件中包含的所有三個第三方 JAR 文件。第三方包的許可條款允許您重新發布本文包含的所有包,但是如果有興趣對這些包做些修改,請閱讀許可條款。

結束語

使用 TableModel Free 框架,就不用再編寫傳統 TableModel 了。TMF 框架改進了 JTable 和 TableModel 模型之間的 MVC 關系,更清楚地分離了它們。在日后的發布中,您甚至可以在不修改任何模型代碼的情況下,對組件進行熱交換。框架還允許您在模型發生變化時,自動更新視圖,從而消除傳統 TableModel 設計中所必需的視圖和模型之間的通信。

TMF 框架還會極大地減少開發 GUI 所需的時間,特別是在處理 JTable 時。幾年以前,我處理的一個應用程序中有 150 多個 JTable,每個表都來自同一個原始表模型,該應用程序可以作為示例。使用 TMF 框架,我們只用 150 行代碼就能解決問題;但是不幸的是,當時還沒有 TMF,所以我們最后編寫了 15,000 行額外的代碼,才生成必需的表模型。這不但增加了開發時間,還增加了測試和調試的時間。

與使用傳統 TableModel 相比,使用 TMF 框架使您到了一個更加容易配置所有 JTable 的時代。請想像這樣一個 POS 應用程序:該應用程序被銷售給了 5 個不同的客戶,每個客戶都有一套特定的信息,所以每個用戶都想有一組顯示在 GUI 上的特定的列。如果沒有 TMF 框架,您就必須為每個客戶都生成一組特定的 TableModel —— 由此,也就生成了一組特定的應用程序。而使用可配置的 XML 文件,每個客戶都可以使用相同的應用程序,客戶所在地的業務分析師可以根據需要修改 XML 文件。請想像一下,這節約了多少開發和支持成本!

TableModel Free 框架解決了 Swing 開發人員社區的特定需求:減少了處理 JTable 時的開發時間和維護開銷,提高了它們對終端用戶的易用性。Swing 桌面正在回歸,使用像 TMF 框架這樣的工具,開發人員會發現可以更容易地使用 Swing 和開發 GUI 應用程序。您要做的第一步就是用 TMF 框架的一行代碼代替您所有的 TableModel,把所有 TableModel 都永遠地拋到虛擬空間的黑洞中去吧。


下載

名字 大小 下載方法
j2x.zip ? HTTP
lib.zip ? HTTP
docs.zip ? HTTP

關于下載方法的信息


參考資料

  • 您可以參閱本文在 developerWorks 全球站點上的?英文原文。?

  • 請單擊?Code圖標(或者參閱?下載部分),下載在本文中討論的源代碼、第三方 JAR 文件和 Javadoc。?

  • The Jakarta Commons Collections提供了 Java Collections 之外的其他功能。?

  • Castor是一個強大的 XML 解析器。?

  • 如果對 XML 感興趣,請訪問?developerWorksXML zone?,那里有大量優秀的內容,既適合初學者,也適合專家。?

  • Michael Abernethy 的“?Go state-of-the-art with IFrame,”(?developerWorks,2004 年 3 月)中對 IFrame 進行了介紹,它是 J2X 項目的另外一個組件。它允許您創建定制設計的應用程序窗口。?

  • 由 Andy Clark 和 Dave Smith 合著的“?Building a Customized Tree View,”(?developerWorks,2001 年 1 月)提供了在 Swing 組件中使用 MVC 的技巧。?

  • Malcolm Davis 撰寫的“?Struts, an open-source MVC implementation,”(?developerWorks,2001 年 2 月)提供了在 Web 應用程序中使用的 MVC。?

  • Mitch Goldstein 撰寫的“?Swing model filtering,”(?developerWorks,2001 年 2 月)提供了用于 TableModel 設計的 TMF 框架的替代方案。?

  • Brett Spell 撰寫的“?Rendering cells in Swing's JTable component,”(?developerWorks,2000 年 11 月)通過提供關于繪制單元格的技巧,添加了一項 JTable 功能。?

  • 在?developerWorksJava 技術專區?中,可以找到 Java 編程各個方面的文章。?

  • 參閱?Developer Bookstore,以獲得技術書籍的完整清單,其中包括數百本?Java 相關主題的書籍。?

關于作者

Michael Abernethy 目前是 WebSphere 系統管理功能性測試團隊的負責人,之前,他在 WebSphere Services 團隊工作了 4 年,一直在 WebSphere 上編寫、部署應用程序。在業余時間里,他還涉獵了 Swing 和 UI 開發。您可以通過 Michael 的郵箱?mabernet@us.ibm.com與他聯系。


總結

以上是生活随笔為你收集整理的用 TableModel Free 框架简化 Swing 开发——JTable的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。