出版時間:2008-9 出版社:清華大學出版社 作者:(美)波德魯,(美)圖拉赫,(美)威爾蘭格 著,葉亮 譯 頁數(shù):445 譯者:葉亮
Tag標簽:無
前言
歡迎進入NetBeans 平臺的富客戶端開發(fā)世界?! ‰m然因特網(wǎng)的蓬勃發(fā)展使得人們更熱衷于服務器端的開發(fā),但對高質(zhì)量桌面軟件的需求卻從未減少,反而在一定程度上有所增加。其中部分原因包括: Web頁面—— 通常作為服務器驅(qū)動的應用程序的界面,經(jīng)常無法充分滿足最終用戶的需求?! 〔⒉皇撬械膽枚家蟪掷m(xù)的網(wǎng)絡連接,很多應用需要脫機運行?! ”緯鴮⒅攸c介紹如何使用NetBeans平臺作為框架,開發(fā)“一次編寫,處處運行”的富客戶端應用程序。NetBeans平臺是NetBeans IDE(集成開發(fā)環(huán)境)的基礎(chǔ)。數(shù)以萬計的開發(fā)者利用NetBeans IDE完成了不同規(guī)模和復雜度的應用程序。毋庸置疑,NetBeans平臺十分強大而健壯,完全可以作為大多數(shù)應用程序的基礎(chǔ),無論它們是商業(yè)的還是內(nèi)部的解決方案。除此之外,本書還會介紹如何編寫應用于NetBeans IDE本身的插件模塊?! 「豢蛻舳藨贸绦颉 案豢蛻舳藨贸绦颉钡降资侵甘裁茨??富客戶端應用程序是指絕大多數(shù)功能(可以不是全部)運行在用戶本地系統(tǒng)上的應用程序。與之相反的是Web應用程序,它的所有功能完全依賴于運行在遠程服務器上的代碼,用戶通常使用Web瀏覽器訪問Web應用程序?!案豢蛻舳恕边@個詞可以被當作是 “桌面應用程序”的一個時髦的綽號。舉例來說,NetBeans IDE本身就是一個典型的富客戶端應用程序?! ∈裁词荖etBeans NetBeans是一個流行的、屢獲殊榮的、用于Java開發(fā)的集成開發(fā)環(huán)境(IDE)。它的核心是NetBeans平臺—— 一個模塊化的、可擴展的應用程序框架。所以,NetBeans IDE本身是NetBeans 平臺以及一系列模塊的完美集合。 在早期發(fā)展階段,為了使NetBeans IDE的開發(fā)更加靈活,它的體系結(jié)構(gòu)被設計得高度模塊化。NetBean IDE模塊化的體系結(jié)構(gòu)帶來了如下優(yōu)勢: 創(chuàng)建新特性十分簡單?! ∮脩艨梢暂p松地增加或刪除功能?! “惭b后,用戶可以方便地更新某個特性,而不會影響其他功能?! etBeans平臺高度模塊化的特點吸引了全世界的眾多開發(fā)者。數(shù)量眾多的NetBeans平臺應用應運而生。NetBeans IDE就是其中最著名的一個。NetBeans平臺被用于各行各業(yè)的應用程序的開發(fā),從語音處理到地質(zhì)填圖再到股票交易?! 槭裁词褂肗etBeans 基于NetBeans平臺的應用程序有很多優(yōu)勢,其中首屈一指的當然是其真正的跨平臺特性。實際上,開發(fā)跨平臺的富客戶端應用程序有很多種方法。例如,可以使用Swing組件自行編寫桌面應用程序的所有模塊。但是,如果使用NetBeans平臺的話,可以直接使用應用程序所需的眾多強大的構(gòu)造模塊和底層構(gòu)架,不用再像以前那樣從頭開始編碼了。顯然,這將節(jié)省大量的時間。開發(fā)者可以根據(jù)應用程序的邏輯編寫新的Swing組件,并將其加入到NetBeans平臺中,也可以在NetBeans平臺中直接使用諸如JGraph、JFreeChart等第三方庫??偠灾?,利用NetBeans平臺可以很容易地開發(fā)出健壯且靈活的應用程序。開發(fā)者只需要關(guān)注應用程序的業(yè)務邏輯。就像JSF(JavaServer Faces)技術(shù)和Struts是為了Web開發(fā)而生,NetBeans平臺是為了Swing開發(fā)而生?! ∫韵率荖etBeans平臺最突出的幾個優(yōu)勢: NetBeans是免費的,任何人都可以免費使用其代碼,無論將它用于開發(fā)商業(yè)軟件還是非商業(yè)軟件都是如此?! etBeans是一個成熟的、功能豐富的應用程序框架。NetBeans平臺由眾多的組件構(gòu)成,它們原本是為NetBeans IDE服務的—— 不計其數(shù)的軟件工程師使用過NetBeans IDE。但實際上,NetBeans平臺可以用來開發(fā)任何類型的桌面應用程序,不僅僅是某種集成開發(fā)環(huán)境或類似的應用。NetBeans平臺為應用程序提供了高質(zhì)量的基礎(chǔ)?! etBeans是一個真正的“一次編寫,處處運行”的平臺。NetBeans基于Swing—— 一個純Java的可視化工具集,它是所有桌面Java安裝版的一部分?! etBeans技術(shù)是標準化的、開源的。這意味著,任何人都不用擔心在NetBeans平臺基礎(chǔ)上進行開發(fā)會產(chǎn)生專利鎖定的問題?! etBeans IDE的插件擁有大量的潛在用戶。假如某人希望向公眾展示一些新技術(shù),他只需要開發(fā)一個相應的NetBeans IDE插件模塊,將其發(fā)布在NetBeans 插件的門戶網(wǎng)站上(http://plugins.netbeans.org/PluginPortal),立刻就可以輕松地吸引眾多用戶。 NetBeans擁有一個活躍的社區(qū)。NetBeans平臺的成長正是得益于這個強大社區(qū)中的眾多開發(fā)者,他們熱切地希望與大家共享他們的經(jīng)驗。如果你正好有一個關(guān)于NetBeans的問題,那么請去社區(qū)中尋找答案。因為很可能某人曾經(jīng)遭遇過和你一樣的問題,他可以幫助你?! etBeans平臺為開發(fā)者提供哪些資源 NetBeans平臺為開發(fā)者提供的資源包括:一系列豐富的基礎(chǔ)功能,可用于創(chuàng)建新特性的擴展API,以及一組用來協(xié)助開發(fā)的強大工具。 開發(fā)基于NetBeans平臺的應用程序時,開發(fā)者可以利用的資源包括: 窗口系統(tǒng)(Window System),它極大地簡化了在一個frame中對眾多組件的操作?! 〔僮飨到y(tǒng)(actions system),利用它可以簡單地以聲明的方式安裝或卸載菜單項、工具欄、鍵盤快捷鍵等資源?! ∽詣痈聶C制,為應用程序提供了一種動態(tài)更新的方式?! etBeans IDE本身提供的所有特性都可以用來簡化應用程序的開發(fā)。例如,代碼補全和高效的GUI編輯器(之前的代號叫做Matisse)—— 通過簡單地拖拽和重新排列組件,能夠可視化地創(chuàng)建用戶界面。除此之外,NetBeans IDE還提供了針對模塊開發(fā)的特殊功能。例如模塊模板和方便的模塊測試功能 —— 隨時可以把模塊安裝或者重新載入到當前運行的IDE中。 得益于NetBeans平臺所鼓勵使用的模塊化編碼技術(shù),基于NetBeans平臺的應用程序會更加健壯?! 槭裁撮喿x本書 NetBean IDE越來越流行,同時,越來越多的人已認識到利用NetBeans平臺可以很方便地創(chuàng)建任何類型的桌面應用程序。顯然,大家急切地需要一本指導書。實際上,有很多NetBeans平臺的信息都散布在不同地方,但沒有一本完整的教材來演示如何使用整個NetBeans平臺。本書集作者多年積累的經(jīng)驗、最佳實踐和實用信息于一身?! ”緯鴮椭x者快速掌握模塊的開發(fā),并且指導讀者學習絕大多數(shù)重要的API。在這個過程中,讀者也將學習到一些使NetBeans可靠而又靈活的開發(fā)實踐?! ∪绾问褂帽緯 ”緯?2個章節(jié)、2個用例及3個附錄組成?! 〉?章,做一些準備工作,演示創(chuàng)建一個模塊的基本過程?! 〉?章和第3章,討論模塊化開發(fā)的優(yōu)勢并提供NetBeans平臺模塊化構(gòu)架的概況?! 〉?章和第5章,解釋NetBeans模塊協(xié)同工作的基本概念,展示NetBeans平臺使得模塊化應用高耦合的機制?! 〉?章,介紹文件系統(tǒng)(Filesystems)API,它是NetBeans平臺處理用戶數(shù)據(jù)和系統(tǒng)配置數(shù)據(jù)的基礎(chǔ)構(gòu)架。 第7章,鞏固第6章的內(nèi)容,并且展示如何基于NetBeans平臺創(chuàng)建一個簡單的導航(Navigator)組件?! 〉?章,解釋并演示在NetBeans中創(chuàng)建一個成熟的多窗口應用程序所需的組件和特性?! 〉?章,介紹Node和Explorer API,利用它們可以以多種方式向用戶展示數(shù)據(jù)結(jié)構(gòu)?! 〉?0章,重點介紹數(shù)據(jù)系統(tǒng)(Datasystems)API,利用它可以以多種方式、簡單地在程序中操作特定類型的文件?! 〉?1章,介紹NetBeans IDE的GUI構(gòu)建器,演示如何利用它簡化基于NetBeans平臺應用程序的用戶界面開發(fā)?! 〉?2章,在第11章的基礎(chǔ)上,展示如何為單個文件的內(nèi)容提供多種表現(xiàn)形式?! 〉?3章和第14章,展示為某種文件類型加入編輯特性的方法?! 〉?5章,解釋如何創(chuàng)建一個對象調(diào)色板,并通過一個實例演示如何實現(xiàn)從調(diào)色板中拖拽代碼片段到文本編輯器中?! 〉?6章和第17章,介紹如何開發(fā)更多的編輯特性?! 〉?8章,演示如何為應用程序加入用戶定制選項。 第19章,以Wicket為例,介紹如何為IDE加入對Web應用框架的支持。 第20章,介紹如何讓NetBeans平臺應用程序支持使用Web服務。 第21章,演示如何在應用程序中集成幫助文檔?! 〉?2章,展示如何將更新后的模塊(和新模塊)加入到用戶的動態(tài)更新中心?! ∽詈髢烧率荖etBeans平臺的用戶案例。第23章介紹的案例演示了如何在NetBeans IDE中集成現(xiàn)有開發(fā)工具。第24章的案例展示了如何創(chuàng)建一個創(chuàng)建音頻的編輯器?! 「戒浿械男畔⒂兄趯W習如何提高代碼的健壯性、可讀性、靈活性及性能?! ”緯]有涉及到很多NetBeans IDE本身的一些特性,而是更關(guān)注實現(xiàn)這些特性的API。如果讀者對如何使用NetBeans IDE開發(fā)標準Swing、Web、企業(yè)、移動或者其他Java應用程序感興趣,可以找到很多優(yōu)秀的參考資源。例如NetBeans IDE Field Guide一書(同樣由Prentice Hall出版),NetBeans IDE自帶的文檔,以及www.netbeans.org和http://wiki.netbeans.org 網(wǎng)站上的資源。 沒有一本參考書可以代替所有參考文檔,本書也不例外。讀者可以在NetBeans平臺的網(wǎng)站(http://platform.netbeans.org) 上找到完整的NetBeans API參考文檔?;蛘咧苯油ㄟ^NetBeans IDE的“更新中心”下載它。開發(fā)者問題集(Developer FAQ,http://wiki.netbeans.org/wiki/view/NetBeansDeveloperFAQ)也是一個很好的資源,讀者可以在其中查到不斷重復的問題的答案。NetBeans郵件列表—— 特別是 dev@openide.netbeans.org郵件列表 —— 對于尋求罕見問題的答案特別有用。如果讀者正計劃開發(fā)NetBeans模塊,我們強烈建議注冊參與這個郵件列表。通過它,讀者可以與整個NetBeans開發(fā)團隊和社區(qū)交流。當然,其中也包括本書的作者?! ≡陂_始開發(fā)NetBeans模塊之前,最好檢查一下更新中心(在“工具”菜單中),確保擁有最新版本的NetBeans模塊開發(fā)工具。這些工具包含很多模板以及其他簡化模塊開發(fā)的特殊支持?! ∪绾胃隆 ≡L問本書的主頁(www.netbeans.org/books/rcp.html),下載更新和其他額外的內(nèi)容。本書的內(nèi)容主要針對NetBeans平臺的5.5版本,它是目前最新的正式發(fā)布版。新版本會持續(xù)地跟進。盡管本書的內(nèi)容對NetBeans 6.0版本也有價值,同時也適用于未來的其他版本。但建議讀者最好訪問“升級指南”(www.netbeans.org/download/dev/javadoc/apichanges.html),以便能在學習5.5版本之后明白有哪些API改變了、增強了或是拋棄了。本書會對6.0版本改變的地方加以特別注明。
內(nèi)容概要
這是一本有關(guān)NetBeans富客戶端應用程序開發(fā)的權(quán)威指南,內(nèi)容涵蓋了NetBeans 5.5和6.x版本,重點介紹了如何使用NetBeans平臺作為框架,開發(fā)“一次編寫,處處運行”的富客戶端應用程序。旨在幫助讀者掌握NetBeans模塊的開發(fā),精通NetBeans的主要API,以及學會一些構(gòu)建可靠桌面軟件的技術(shù)與技巧?! ”緯扇豁敿塏etBeans專家聯(lián)合編寫,并由Sun中國的專家團隊葉亮等人翻譯和審校,是中國讀者不可多得的NetBeans學習用書,也是Sun中國技術(shù)社區(qū)推薦的NetBeans技術(shù)用書。
作者簡介
Tim Boudreau是NetBeansTM:The Definitive Guide(由O’Reilly出版)一書的合著者,開源NetBeans核心團隊的成員,一直致力于NetBeans項目的開發(fā)。
書籍目錄
第1章 NetBeans平臺入門 1.1 配置IDE 1.2 NetBeans IDE基礎(chǔ) 1.2.1 創(chuàng)建模塊 1.2.2 創(chuàng)建應用程序 1.2.3 使用文件模板 1.2.4 聲明依賴關(guān)系 1.2.5 運行模塊 1.2.6 定制應用程序 1.2.7 發(fā)布應用程序 第2章 模塊化編程的優(yōu)勢 2.1 分布式開發(fā) 2.2 模塊化應用 2.2.1 版本 2.2.2 次級版本信息 2.2.3 依賴管理 2.3 模塊化編程宣言 2.4 使用NetBeans進行模塊化編碼 第3章 模塊化的體系結(jié)構(gòu) 3.1 模塊—— 程序的裝配單元 3.2 模塊的類型 3.2.1 最終用戶界面模塊 3.2.2 簡單程序庫 3.2.3 多廠商支持 3.2.4 模塊庫 3.3 模塊生命周期 3.4 模塊群組 第4章 低耦合的交互 4.1 注冊和查找 4.2 MetaInf服務 4.3 全局Lookup 4.4 編寫擴展點 第5章 Lookup 5.1 擁有Lookup的對象 5.2 Lookup作為通信機制 5.3 Lookup和代理 5.4 Lookup和選擇 5.5 編寫Lookup敏感的操作 5.6 追蹤全局選擇 5.7 NetBeans API中遺留的Lookup模式變種 5.8 常見的Lookup模式 第6章 Filesytems 6.1 FileSystems 和FileObjects 6.2 需要處理什么類型的FileSystem 6.3 層次 6.4 XML文件系統(tǒng) 6.5 聲明式注冊二:系統(tǒng)文件系統(tǒng) 6.5.1 “系統(tǒng)文件系統(tǒng)”是如何工作的 6.5.2 “系統(tǒng)文件系統(tǒng)”是可讀寫的 6.5.3 使用“系統(tǒng)文件系統(tǒng)”的FileChangeEvents 6.5.4 探索系統(tǒng)文件系統(tǒng)——菜單 6.6 從FileObject到Java對象 6.6.1 使用工廠方法從.instance文件創(chuàng)建對象 6.6.2 通過代碼訪問“系統(tǒng)文件系統(tǒng)” 6.6.3 使用.settings文件 6.7 瀏覽“系統(tǒng)文件系統(tǒng)” 6.8 小結(jié) 第7章 線程、偵聽者模式和MIME查找 7.1 創(chuàng)建模塊和SPI 7.2 實現(xiàn)ListModelProvider 7.2.1 建立依賴 7.2.2 創(chuàng)建XmlListModelProvider 7.2.3 注冊XmlListModelProvider 7.3 提供一個UI組件 7.3.1 MIME查找SPI和API 7.3.2 提供一個窗口組件顯示列表模型 7.4 使用Pseudo Navigator 7.5 小結(jié):Pseudo Navigator——這張圖片有什么錯誤? 第8章 窗口系統(tǒng) 8.1 窗口系統(tǒng)的作用 8.2 “窗口系統(tǒng)API”中的類 8.3 使用TopComponent 8.4 在會話間持久化狀態(tài) 8.5 窗口系統(tǒng)持久化數(shù)據(jù) 8.6 創(chuàng)建編輯器樣式的TopComponent(以非聲明的方式) 8.7 高級窗口系統(tǒng)配置:自定義Mode 8.8 使用TopComponent群組第9章 Node、Explorer視圖、Action和Presenter 9.1 Node API 9.2 Explorer API 9.2.1 explorer視圖組件的類型 9.2.2 創(chuàng)建顯示Node的TopComponent 9.2.3 添加詳細視圖 9.2.4 使用Explorer API添加另一個詳細視圖 9.3 Action 9.3.1 Presenter 9.3.2 Action API和NetBeans標準操作 9.3.3 在菜單、工具欄和快捷鍵中安裝全局Action 9.3.4 上下文感知操作 9.4 Node屬性 9.5 Node和DataObject:創(chuàng)建系統(tǒng)文件系統(tǒng)瀏覽器 9.6 小結(jié):節(jié)點、表單屬性和用戶界面設計 第10章 DataObject和DataLoader 10.1 DataObject來自哪里? 10.2 添加對新文件類型的支持 10.2.1 為NetBeans添加對ManiFest文件的支持 10.2.2 由manifest文件提供Manifest對象 10.2.3 由ManifestDataObject和ManifestDataNode提供ManifestProvider 10.2.4 圖標徽章 10.2.5 用JUnit測試ManifestDataObject 10.3 在內(nèi)部使用自定義的文件類型 10.4 序列化對象和系統(tǒng)文件系統(tǒng) 第11章 圖形用戶界面 11.1 介紹 11.2 新建GUI窗體 11.3 在窗體中放置和排列組件 11.4 設置組件的大小和大小可調(diào)性 11.5 設定組件的行為和外觀 11.6 生成事件偵聽和處理方法 11.7 定制生成的代碼 11.8 用可視化的方法構(gòu)建瀏覽器視圖 11.9 預覽窗體 11.10 在窗體編輯器中使用自定義的Bean 11.11 使用不同的布局管理器 第12章 多視圖編輯器 12.1 介紹 12.2 入門 12.3 理解多視圖編輯器 12.4 創(chuàng)建編輯器的基礎(chǔ)構(gòu)架 12.5 創(chuàng)建源視圖 12.5.1 描述源MultiViewElement 12.5.2 創(chuàng)建源編輯器 12.5.3 在多視圖編輯器中加入源視圖 12.6 創(chuàng)建可視化視圖 12.7 完成示例 第13章 語法高亮顯示 13.1 介紹 13.2 準備創(chuàng)建語法高亮支持 13.3 創(chuàng)建Token ID 13.4 創(chuàng)建詞法分析器 13.5 擴展選項窗口 13.6 擴展選項窗口 13.7 完成 第14章 完成代碼 14.1 介紹 14.2 理解代碼完成 14.3 代碼完成提示類型 14.4 準備使用CompletionProvider接口 14.5 實現(xiàn)CompletionProvider 14.6 實現(xiàn)CompletionItem 14.7 為CompletionProvider添加過濾器 14.8 為“代碼完成提示框”加入文檔 14.9 為“代碼完成提示框”加入工具提示 第15章 組件面板 15.1 介紹 15.1.1 理解組件面板 15.1.2 創(chuàng)建第一個組件面板 15.2 向組件面板中添加元素 15.2.1 為第一個組件面板添加元素 15.2.2 讓用戶向組件面板中添加元素 15.3 拖放組件元素 15.3.1 定義放置目標 15.3.2 定義拖拽圖像 15.3.3 定義放置事件 15.3.4 定義拖拽動作 15.4 將支持特性添加到組件面板中 15.4.1 為面板添加操作 15.4.2 添加過濾器并刷新面板 15.4.3 添加屬性改變偵聽器 15.4.4 設置面板屬性 15.4.5 提供組件面板管理器 15.5 為文本編輯器創(chuàng)建組件面板 15.5.1 將組件面板與文本編輯器關(guān)聯(lián) 15.5.2 在文本編輯器的組件面板中添加元素 15.5.3 在文本編輯器中格式化被放置的元素 15.5.4 讓用戶在文本編輯器的組件面板中添加元素 第16章 超鏈接 16.1 介紹 16.1.1 準備提供超鏈接 16.1.2 HyperlinkProvider類 16.1.3 快速開始 16.2 使用HyperlinkProvider類的準備工作 16.3 manifest文件中的超鏈接 16.3.1 識別超鏈接 16.3.2 設置超鏈接的長度 16.3.3 打開引用的文檔 16.3.4 完成 第17章 標注 17.1 介紹 17.2 準備創(chuàng)建錯誤標注 17.3 創(chuàng)建錯誤標注 17.3.1 理解錯誤標注DTD 17.3.2 注冊錯誤標注 17.3.3 安裝錯誤標注 17.4 準備使用錯誤標注 17.5 使用錯誤標注 17.5.1 描述標注 17.5.2 掛載和分離標注 17.5.3 定義請求處理任務 17.5.4 標注某行的一部分 17.6 完成 第18章 選項窗口 18.1 介紹 18.2 查看“選項”窗口擴展文件 18.2.1 AdvancedOption類 18.2.2 OptionsPanelController類 18.2.3 可視化選項面板 18.3 創(chuàng)建主面板 18.3.1 第一個主面板 18.3.2 重新排序選項面板 18.4 向“選項”窗口中添加設置 第19章 Web框架 19.1 介紹 19.1.1 支持Web框架的準備工作 19.1.2 WebFrameworkProvider類 19.1.3 快速開始 19.1.4 示例:簡單注冊 19.2 準備使用WebFrameworkProvider類 19.3 為框架提供配置面板 19.3.1 創(chuàng)建配置面板 19.3.2 示例:在WebFramework Provider實現(xiàn)中添加配置面板 19.3.3 編寫配置面板 19.4 創(chuàng)建源代碼結(jié)構(gòu) 19.4.1 準備使用extend()方法 19.4.2 示例:定義extend()方法 19.4.3 創(chuàng)建模板 19.4.4 創(chuàng)建Java文件的模板 19.4.5 準備:利用模板在程序中創(chuàng)建Java文件 19.4.6 利用模板在程序中創(chuàng)建Java文件 19.4.7 嘗試使用框架支持模塊 19.5 讓用戶在“框架”面板中選擇庫 19.6 “項目屬性”對話框和Web框架 19.7 完成 第20章 Web服務 20.1 介紹 20.2 創(chuàng)建和測試Web服務客戶端 20.3 集成Web服務客戶端 第21章 JavaHelp文檔 21.1 創(chuàng)建幫助集 21.2 刪除IDE的幫助集 21.3 標記幫助集的默認文字 第22章 更新中心 22.1 介紹 22.2 添加IDE的更新中心功能 22.3 創(chuàng)建和分發(fā)自動更新描述符 22.3.1 用IDE創(chuàng)建自動更新描述符 22.3.2 上傳自動更新描述符和NBM文件 22.4 分發(fā)自動更新描述符的URL 22.4.1 生成一個注冊自動更新描述符的模塊 22.4.2 讓用戶手動注冊自動更新描述符 22.5 從更新中心下載NBM文件 22.6 將更新發(fā)布到現(xiàn)有模塊 第23章 用例1:跟Jens Trapp學習NetBeans模塊開發(fā) 23.1 介紹 23.2 調(diào)用外部工具 23.2.1 創(chuàng)建Tidy錯誤檢測操作 23.2.2 獲取文件名 23.2.3 運行HTML Tidy 23.2.4 解決依賴 23.2.5 運行示例 23.3 處理輸出 23.3.1 打印輸出 23.3.2 偵聽輸出 23.3.3 解析輸出 23.3.4 在“源代碼編輯器”中標注錯誤 23.4 配置工具 23.4.1 擴展“選項”窗口 23.4.2 持久化選項 23.5 格式化和轉(zhuǎn)換文件 23.5.1 操作文件 23.5.2 查看區(qū)別 23.6 控制轉(zhuǎn)換 23.6.1 創(chuàng)建向?qū)? 23.6.2 連接向?qū)?第24章 用例2:Rich Unger應用程序開發(fā) 24.1 介紹 24.2 開始 24.3 創(chuàng)建audio/wav的 MIME類型支持 24.4 在WavDataObject中封裝音頻數(shù)據(jù) 24.5 創(chuàng)建查看WAV文件的組件 24.6 將WAV編輯器轉(zhuǎn)變?yōu)槎嘁晥D編輯器 24.7 創(chuàng)建插入額外視圖的API 24.8 實現(xiàn)API,提供新視圖 附錄A 高級模塊系統(tǒng)開發(fā)技術(shù) 附錄B NetBeans中的常見習慣和代碼模式 附錄C 性能
章節(jié)摘錄
24.6 將WAV編輯器轉(zhuǎn)變?yōu)槎嘁晥D編輯器 本小節(jié)將介紹如何將WavComponent改為多視圖組件。關(guān)于多視圖的詳細介紹,請參考第12章?! avOpenSupport需要返回的是一個多視圖組件,而不是現(xiàn)在比較精簡的WavComponent?! rotected CloneableTopComponent createCloneableTopComponent() { // Create an array of MV descriptors with only one view of the // data (the one weve already created - the waveform view) WavPanelMultiViewDescriptor main = new WavPanelMultiViewDescriptor(); MultiViewDescription[] descArry = { main }; // Initialize the view with data WavDataObject dobj = (WavDataObject)entry.getDataObject(); main.setWavDataObject(dobj); // Create the multiview CloneableTopComponent tc = MultiViewFactory. createCloneableMultiView(descArry, main, new CloseHandler()); tc.setDisplayName(dobj.getName()); return tc; } 這段代碼引入了兩個新類:CloseHandler 和WavPanelMultiViewDescriptor。CloseHandler的名稱表明了自己的作用。它負責處理多視圖組件的關(guān)閉。下面的實現(xiàn)會詢問用戶文件是否應該在關(guān)閉前保存。根據(jù)用戶對此的選擇,對每個元素調(diào)用ProceedAction或者DiscardAction。在沒有看到其他不同的實現(xiàn)之前,這個實現(xiàn)應該是默認設置: private static class CloseHandler implements CloseOperationHandler, Serializable { private static final long serialVersionUID = 1L; public boolean resolveCloseOperation( CloseOperationState[] elements) { NotifyDescriptor nd = new NotifyDescriptor.Confirmation( "Save before closing?"); DialogDisplayer.getDefault().notify(nd); if (nd.getValue().equals(NotifyDescriptor.YES_OPTION)) { for (CloseOperationState element : elements) { element.getProceedAction().actionPerformed( new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "xxx")); } return true; } else if (nd.getValue().equals(NotifyDescriptor.NO_OPTION)) { for (CloseOperationState element : elements) { element.getDiscardAction().actionPerformed( new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "xxx")); } return true; } else { // Cancel return false; } } } WavPanelMultiViewDescriptor除了作為MultiViewElement的工廠類之外,還為每個視圖提供一些描述(名稱、圖標等): public class WavPanelMultiViewDescriptor implements MultiViewDescription, Serializable { private static final long serialVersionUID = 1L; public static Image ICON = Utilities.loadImage("org/foo/wavutils/sampleGraph.gif"); private WavDataObject dobj; public int getPersistenceType() { return TopComponent.PERSISTENCE_ALWAYS; } public String getDisplayName() { return "Waveform"; } public Image getIcon() { return ICON; } public HelpCtx getHelpCtx() { return null; } public String preferredID() { return "wavEditor"; } public MultiViewElement createElement() { return new WavComponent(dobj); } public void setWavDataObject(WavDataObject wav) { dobj = wav; } private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); } } 現(xiàn)在,把老的WavComponent轉(zhuǎn)變?yōu)橐粋€MultiViewElement。元素本身再也不必是一個TopComponent的實例(不過,即使是的話也無妨)?! ublic class WavComponent implements MultiViewElement { private static final CloseOperationState CLOSE_OPERATION_STATE = createCloseOperationState(); private transient WavPanel wavPanel; public WavComponent(DataObject dobj) { super(); wavPanel = new WavPanel(dobj); } public Action[] getActions() { return new Action[0]; } public Lookup getLookup() { return wavPanel.getWavDataObject().getNodeDelegate(). getLookup(); } public UndoRedo getUndoRedo() { return new UndoRedo.Manager(); } public JComponent getVisualRepresentation() { return wavPanel; } public JComponent getToolbarRepresentation() { // We dont need any widgets on the toolbar return new JPanel(); } public CloseOperationState canCloseElement() { if (wavPanel.getWavDataObject().isModified()) { return CLOSE_OPERATION_STATE; } else { return CloseOperationState.STATE_OK; } } public void setMultiViewCallback(MultiViewElementCallback multiViewElementCallback) { // Dont need this } // Semantics similar to the equivalent methods in TopComponent public void componentDeactivated() {} public void componentActivated() {} public void componentHidden() {} public void componentShowing() {} public void componentClosed() {} public void componentOpened() {} public Object writeReplace() { return null; } private static CloseOperationState createCloseOperationState() { return MultiViewFactory.createUnsafeCloseState( "xxx", new ProceedAction(), new DiscardAction()); } private static class ProceedAction extends NodeAction { protected void performAction(Node[] node) { try { if (node != null && node.length > 0) { SaveCookie sc = (SaveCookie)node[0].getCookie(SaveCookie.class); sc.save(); } } catch(IOException ex) { ErrorManager.getDefault().notify(ex); } } protected boolean enable(Node[] node) { return true; } public String getName() { return "Save"; } public HelpCtx getHelpCtx() { return null; } } private static class DiscardAction extends NodeAction { protected void performAction(Node[] node) { if (node != null && node.length > 0) { DataObject dobj = (DataObject)node[0].getCookie(DataObject.class); try { // Throw away whats in memory. // The DataObject will be recreated from disk. dobj.setValid(false); } catch (PropertyVetoException ex) { ErrorManager.getDefault().notify(ex); } } } protected boolean enable(Node[] node) { return true; } public String getName() { return "Discard"; } public HelpCtx getHelpCtx() { return null; } } } 此時,編輯器應該和前一小節(jié)中的完全一樣,但它是在多視圖窗口中,如圖24-10所示?! D24-10 只有一個視圖的“多視圖”WAV編輯器 接下來定義一個擴展點,讓其他模塊可以在多視圖窗口中插入新的視圖?! ?4.7 創(chuàng)建插入額外視圖的API 在NetBeans平臺上創(chuàng)建API的第一步是新建一個獨立的包(例如,org.foo.wavsupport.api))。依賴于wavsupport的模塊應該只能訪問這個包中的類。為了確保這一點,請在wavsupport的“項目屬性”窗口中,把這個包指定為“公共包”。如圖24-11所示?! D24-11 一個公共的API包 這個API的目的是讓其他的模塊可以提供它們自己的MultiViewDescriptions。這意味著至少能夠從其他模塊中收集MultiViewDescription的實例,然后把它們插入多視圖窗口中?! 〉?,為了讓這些其他模塊獲得足夠的信息以創(chuàng)建有意義的界面,它們需要訪問WavDataObject。所以,在API包中創(chuàng)建一個子接口: public interface WavViewDescriptor extends MultiViewDescription, Serializable { void setWavDataObject(DataObject dobj); } 請注意,setWavDataObject()方法接受一個通用的DataObject類型對象作為參數(shù),而不是更加特殊的WavDataObject。這是因為WavDataObject并不在API包中。最好能夠讓客戶模塊需要的任何數(shù)據(jù)都能夠在DataObject的cookie集找到?! ≡贏PI包中創(chuàng)建一個新的子接口,命名為WavCookie,將WavDataObject中所有公共常量都移到這個接口中。同時,再為所有希望WavDataObject對外公開的方法聲明公共API方法: public interface WavCookie extends Node.Cookie { public static final String PROP_WAVEFORM = "waveform"; AudioFormat getAudioFormat(); WrappedAudioInputStream getAudioInputStream(); void setAudioInputStream( WrappedAudioInputStream is ); void addPropertyChangeListener(PropertyChangeListener l); void removePropertyChangeListener(PropertyChangeListener l); } 然后,讓WavDataObject實現(xiàn)這個接口: public class WavDataObject extends MultiDataObject implements WavCookie { ... } 請注意,不需要像在執(zhí)行打開和保存cookie操作時一樣把WavDataObject顯式式添加到它的cookie集中。這是一個特例。所有DataObject都會自動地加入到它們自己的cookie集中。目前WavOpenSupport類僅僅實例化WavPanelMultiViewDescriptor,然后把它放在一個單元素的數(shù)組中傳遞給MultiViewFactory?,F(xiàn)在,將描述符放進一個未知大小的列表中,作為第一個元素,使用Lookup(有關(guān)Lookup的詳細信息,請參閱第4章的4.3節(jié))填充列表中的其他元素: WavViewDescriptor main = new WavPanelMultiViewDescriptor(); List all = new ArrayList(); all.add(main); Lookup.Template template = new Lookup.Template(WavViewDescriptor.class); Lookup.Result result = Lookup.getDefault().lookup(template); for (Object wvd : result.allInstances()) { all.add((WavViewDescriptor)wvd); } 然后把數(shù)據(jù)對象的引用傳遞給所有描述符: for (WavViewDescriptor wvd : all) { wvd.setWavDataObject(dobj); } 最后,把列表轉(zhuǎn)換成數(shù)組,傳遞給MultiViewFactory: WavViewDescriptor[] allArray = new WavViewDescriptor[all.size()]; all.toArray(allArray); CloneableTopComponent tc = MultiViewFactory.createCloneableMultiView(allArray, main, new CloseHandler()); 至此,客戶模塊就可以實現(xiàn)公開的WavViewDescriptor接口,并使用WavCookie提供的信息在多視圖窗口中提供一個新的標簽頁——這些都完全不需要編輯wavsupport模塊的源代碼?! ?4.8 實現(xiàn)API,提供新視圖 現(xiàn)在是時候成為我們自己API的客戶,創(chuàng)建一個新模塊,為WAV文件提供一個不同的可視化視圖。為了方便讀者,wavutils模塊包含了組件FFTGraph,它基于一個在網(wǎng)上找到的公開域FFT庫(感謝來自賓夕法尼亞大學的Tsan-Kuang Lee!),可以繪制頻率域視圖?! ∈紫仍谀K套件中創(chuàng)建一個新模塊,命名為fftview。別忘記將wavsupport 和wavutils加入到它依賴的模塊集中?! 〗又?,創(chuàng)建API接口 WavViewDescriptor的實現(xiàn): public class FFTViewDescriptor implements WavViewDescriptor { private static final long serialVersionUID = 1L; public static Image ICON = Utilities.loadImage("org/foo/wavutils/sampleGraph.gif"); private DataObject dobj; public int getPersistenceType() { return TopComponent.PERSISTENCE_ALWAYS; } public String getDisplayName() { return "Frequency Domain"; } public Image getIcon() { return ICON; } public HelpCtx getHelpCtx() { return null; } public String preferredID() { return "FFT"; } public MultiViewElement createElement() { return new FFTComponent(dobj); } public void setWavDataObject(DataObject wav) { dobj = wav; } private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); } } 然后,還要再創(chuàng)建一個類,提供真正的組件: public class FFTComponent implements MultiViewElement { private DataObject dobj; private final FFTGraph graph = new FFTGraph(); public FFTComponent(DataObject dobj) { super(); this.dobj = dobj; final WavCookie c = (WavCookie)dobj.getCookie(WavCookie.class); assert(c != null); graph.createGraph(c.getAudioInputStream()); c.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName(). equals(WavCookie.PROP_WAVEFORM)) { WrappedAudioInputStream wais = c.getAudioInputStream(); if (wais == null) graph.clearGraph(); else graph.createGraph(wais); } } }); } public JComponent getVisualRepresentation() { return graph; } public JComponent getToolbarRepresentation() { return new JPanel(); } public void setMultiViewCallback( MultiViewElementCallback multiViewElementCallback) { // Do nothing (we dont need the callback) } public CloseOperationState canCloseElement() { // The main wav component handles asking the user to save. // _This_ component is OK, whatever the outcome. // If the main component needed to provide any visual // feedback before saving/closing, this component could // have its own Proceed/Discard actions return CloseOperationState.STATE_OK; } public void componentDeactivated() {} public void componentActivated() {} public void componentHidden() {} public void componentShowing() {} public void componentClosed() {} public void componentOpened() {} public Object writeReplace() { return null; } public Action[] getActions() { return new Action[0]; } public Lookup getLookup() { return dobj.getNodeDelegate().getLookup(); } public UndoRedo getUndoRedo() { return new UndoRedo.Manager(); } } 剩下的最后一步是發(fā)布這個實現(xiàn),讓WavOpenSupport中的Lookup代碼知道在哪里能找到它。最簡單的方法是在src/META-INF/services/org/foo/wavsupport/api/WavViewDescriptor中新建一個文件,其中包含下列內(nèi)容: org.foo.fftview.FFTViewDescriptor 現(xiàn)在運行應用程序,應該能夠看到兩個視圖,如圖24-12所示。 圖24-12 一個WAV文件的頻率域視圖 在全局Lookup中查詢作為API的接口的實例是非常有用的技術(shù)。特別是對于一些特殊情況就更加有幫助——例如,必須集成API經(jīng)常改變的產(chǎn)品或庫,或者集成相互競爭的廠家的多個產(chǎn)品。開發(fā)者定義的接口會成為一個穩(wěn)定的“橋梁”,每一個客戶模塊都是一個接口的實現(xiàn),它們內(nèi)部可以使用不同特定廠家的API?! ±?,假設正在構(gòu)建一個填寫稅務表格的軟件,開發(fā)者可能擁有一個接口,用來向客戶模塊查詢稅率、法律和表格要求的格式。然后為不同的權(quán)限提供不同的模塊。到第二年,只需要更新這些模塊即可,而應用程序的核心照常工作,無需改變。
媒體關(guān)注與評論
我訪問過一次中國,只去了北京。此時,當我提筆寫下這段文字時正是在2008年8月8日——奧林匹克運動會開幕的日了——這不禁讓我想起那次印象深刻的北京之旅。在北京,我們見到了眾多的Java開發(fā)者,他們非常熱情,積極地與我們聊天和討論。感謝葉亮讓中國的開發(fā)者也能夠看到這本書。對于各位讀者,我想說:“這本書不僅關(guān)乎一個技術(shù)主題,它還包含一種我們努力創(chuàng)造的激情?!蹦诠ぷ髦泻芸赡芤矔羞@樣的激情。如果這本書能夠幫您點燃這種激情,那我們就會很滿足。因為這意味著我們的工作非常有價值?! 猅im Boudreau 在不久的將來,模塊化應用程序會變得越來越重要。在本書中,我們盡力介紹了模塊化所需的基礎(chǔ)知識,并且洋細描述了如何存NetBeans中實現(xiàn)它。我衷心期望尊敬的讀者們都能輕松地讀完這本書,并且學到對今后的職業(yè)生涯都非常有用的知識?! 狫aroslav Tulach 隨著應用程序的規(guī)模和復雜程度不斷增加,您會慢慢發(fā)現(xiàn)NetBeans平臺所提供的服務極其有用。我希望這本書能夠提供您所需的絕大多數(shù)知識,以及觀察應用程序的新視角。最重要的是,我希望本書給您帶來的不僅是有用的知識,還有快樂?! 狦eertjan Wielenga
編輯推薦
開源NetBeans平臺是一個功能極其強大的架構(gòu),主要用于構(gòu)建“只編寫一次,就能到處運行”的富客戶端應用程序。 對于Java開發(fā)人員和架構(gòu)師來說,現(xiàn)有的基本Swing組件已不再滿足他們的開發(fā)需求。為了解決這一問題,這本有關(guān)NetBeans平臺上富客戶端程序開發(fā)的權(quán)威指南便應運而生,旨在幫助讀者掌握NetBeans模塊的開發(fā),精通NetBeans的主要API,以及學會一些構(gòu)建可靠桌面軟件的技術(shù)與技巧。書中的每一章都給出了實際的例子,并按步驟詳細說明了如何在NetBeans平臺上創(chuàng)建功能完善的富客戶端應用程序和NetBeans IDE的插件。 本書主要內(nèi)容: ·模塊開發(fā)對于小、中和大型應用程序的重要意義 ·使用NetBeans加快開發(fā)速度和提高效率 ·利用NetBeans的各項生產(chǎn)率特性(從組件面板到代碼完成) ·在自己開發(fā)的應用程序中利用NetBeans的模塊體系結(jié)構(gòu) ·實現(xiàn)松散耦合的交互,以提高代碼的可維護性和健壯性 ·管理用戶配置和系統(tǒng)配置數(shù)據(jù) ·使用牢固的線程模塊構(gòu)建可重載的組件 ·構(gòu)造復雜的多窗口應用程序,并將富客戶端數(shù)據(jù)結(jié)構(gòu)顯示給用戶 ·添加用戶可配置的選項 ·整合Web服務與NetBeans桌面應用程序 ·自動化模塊更新和為用戶提供幫助
圖書封面
圖書標簽Tags
無
評論、評分、閱讀與下載
NetBeans富客戶端編程權(quán)威教程 PDF格式下載