開發人員和用戶對 Swing 最大的一個抱怨(也是對 Java 編程語言整體上的抱怨)是,客戶端應用程序給人的感覺與本機應用程序的不同。(本機應用程序是指用采用操作系統內置庫的編程語言編寫的應用程序,例如運行在 Windows 上的 Visual C++ 應用程序。)雖然 Java 應用程序表現得像本機應用程序那樣好,但是還是遺漏了某些地方,從而使用戶注意到了差異?;镜膯栴}是 Java 應用程序不能 真正地表現得像本機應用程序那樣,因為本機應用程序有其不公平的一面:它們可以專門針對操作系統進行編寫,這讓它們可以利用特別的本機操作系統函數。Java 代碼受到自己“隨處運行”的咒語限制,并且調用本機函數(例如通過 Java 本機接口)是一個大忌。
![]() |
|
直到現在,Java 開發人員一直希望用這個不足換取能夠編寫在任何操作系統上均可運行的軟件的優勢。但是,隨著 Java SE 5 的發布,特別是 Sun 對增強 Java 桌面的推動,有些開發人員想讓 Java 應用程序和本機應用程序之間的差異最終消失。創建 JDIC 就是了為消除這個差異(請參閱 參考資料)。就像 JDIC Web 站點聲稱的那樣,JDIC 的目標是“讓基于 Java 技術的(‘Java 應用程序’) 在不犧牲平臺獨立性的情況下,成為當前桌面平臺的一等公民。”
這本文將介紹 JDIC 項目,以及它如何成功地讓 Java 客戶端應用程序表現得更加本機化。通過一系列示例,您可以看到 JDIC 中目前所擁有的組件,以及尚在“孵化器”中(工作進行中)的一些組件。我們將要介紹 JDIC 所提供的差不多每個組件,在理想情況下,這些將激發您足夠的興趣,讓您將 JDIC 應用到您的應用程序中,甚至有助于說服您也為這個項目做點貢獻。
關于 JDIC 的一個重要說明是:它仍然是一個 beta 項目,這意味著它還沒有得到任何 JDK 發行版的支持,未來任何時候都可能發生變化。所以一定要把必要的文件與基于 JDIC 的應用程序一同提供,因為沒有 Java 虛擬機(JVM)會支持它。而且因為 API 有可能在發行版之間變化,所以這篇文章中的函數名稱今后可能會有所不同。
它是一個包裝
JDIC 項目有兩個目標:維護 Java API 的跨平臺,讓程序可以在任何機器上運行,并支持人們使用的每個操作系統。因為新功能要求調用每個操作系統的本機函數,所以這顯然處在一個很艱難的位置上。JDIC 是通過將其 Java API 作為所有這些本機調用的包裝器來實現這一點的。JDIC 組件代碼本身指出正在哪個操作系統上運行應用程序,并調用適當的 JNI 函數。(您可以看到,在代碼內部有針對每個操作系統的 if/else 鏈。這就是跨平臺兼容性的代價。)圖 1 演示了 JDIC 包裝本機調用的方式:
![]() |
|
設置
編寫和運行使用 JDIC 應用程序的機器設置比通常情況略微麻煩一些。除了通常的類路徑要求之外,還必須提供 Java 類要調用的操作系統庫。每個操作系統都有不同的操作系統庫,所以如果想使用 JDIC 將應用程序移植到許多不同的操作系統上,則必須為每個操作系統提供一個庫。使用 JDIC 發行版 0.9 時(也就是這篇文章所根據的版本),JDIC 可以處理 Windows、Linux 和 Solaris 系統(要對 Macintosh 的擁護者說抱歉了)。
開始下載跨平臺 JDIC 包,其中包括:
這些文件設置好之后就可以啟動并運行了。如果不能啟動和運行,那么請參閱 JDIC 下載的 README 文件中的文檔,查看特定操作系統的要求。一旦設置就緒,并做好了準備,請繼續閱讀以初步了解這些示例。
![]() |
|
彌補差距
對于每個 JDIC 組件,我都將演示一個小的示例應用程序,每個組件都解決 Java 語言中目前存在的一個特定差距。
WebBrowser 組件
JDIC 項目中的第一個組件(也是該項目的最初靈感) 是 WebBrowser
,它提供了一條接近操作系統內置瀏覽器的途徑。任何熟悉 Swing 的人都非常清楚,在 Java 應用程序中查看 Web 頁面很困難。例如,現有的 Swing 組件 JEditorPane
就做得很糟糕,只能顯示最簡單的 Web 頁面。如果包含任何 DHTML 腳本,那么請忘記它 —— 現有的 Swing 組件不能顯示它。這讓 Swing 開發人員失去了在應用程序中顯示 HTML 頁面的選擇 —— 由于 Web 在任何桌面應用程序中都是如此之重要(用作幫助頁面和 README 文件),所以這是一個很大的障礙。
特別打擊 Swing 開發人員的一個事實是:現在每臺機器上都有功能齊全的瀏覽器,但它們的應用程序仍然無法使用。每個本機應用程序都能使用內置的瀏覽器(Windows 上的 Internet Explorer 或 Linux 機器上的 Mozilla)。Swing 的功能與易于訪問的解決方案之間的巨大差距促使 WebBrowser
成為 JDIC 項目的一個好起點。
WebBrowser
允許 Swing 應用程序將本機瀏覽器嵌入任何應用程序中。但是需要重點指出的是,WebBrowser
僅僅 是 Web 瀏覽器應用程序的呈現部分。這個組件不包含 Back 按鈕、地址欄、狀態欄,或者任何不屬于應用程序呈現部分的內容。但是,正如稍后將看到的,WebBrowser
包含了允許您實現這些常用的瀏覽器特性的方法。
WebBrowser 組件繼承自 java.awt.Canvas class
,這意味著它是一個 Abstract Windowing Toolkit (AWT) 組件。這可能讓熟悉 AWT 和 Swing 組件混合問題(包括重繪問題)的 Swing 開發人員開始擔心。WebBrowser
組件覆蓋了 java.awt.Canvas.paint()
方法,直接把 HTML 呈現給 Canvas 本身,確保了性能的優化。但這對 Swing 開發人員意味著什么呢?這意味著必須把 WebBrowser
包含在 JPanel
中,才能在 Swing 中使用它。這并不像聽起來那么壞。JPanel
是包含 WebBrowser
的邏輯組件,其他 Swing 組件已經有內置的 HTML 支持了。
但是,在可以看到可視組件實際工作的同時,為什么還要一直談論它們呢?以下將要運行的示例是隨 JDIC 下載一起提供的,它與本文其余示例重新打包在一起,可以在一個下載中得到它們(請參閱 下載)。要查看 WebBrowser
示例的實際工作,請運行 demo.Browser.Browser
主類。圖 2 顯示了 WebBrowser 示例的實際工作:
現在應該已經看到了 WebBrowser
的實際工作,讓我們再來看一些 WebBrowser
類中的方法,它們可以讓您創建完整功能的瀏覽器:
back()
forward()
refresh()
stop()
getURL()
setURL()
getContent()
setContent()
WebBrowserEvent
的方法,我將在這一節后面部分進行解釋:
addWebBrowserListener()
removeWebBrowserListener()
executeScript()
executeScript()
方法允許程序執行 JavaScript 腳本,并在裝入的 Web 頁面上或 HTML 內容上執行腳本。這個函數很酷,因為可以用它改變 Web 站點的外觀,甚至是改變第三方站點的外觀:請試著把下面一行添加到演示應用程序中,放在頁面輸入的后面:
|
這為每個裝入的 Web 站點提供了藍色背景,并覆蓋了站點的默認背景色。
WebBrowserEvent
/WebBrowserListener
框架工作的方式與 Swing 中的每個事件/偵聽框架是一樣的,但在該例中,涉及 WebBrowser
能夠觸發的所有與 WebBrowser
有關的操作。對 WebBrowser
觸發的事件感興趣的類,應當通過 WebBrowser
的 addWebBrowserListener()
方法,把自己添加成它的偵聽器。
WebBrowserListener
接口中必須實現的方法是:
簡而言之,這就是 WebBrowser
組件。WebBrowser
類和 WebBrowser
事件/偵聽器框架中的所有方法都允許您創建完整的、實用的 Web 瀏覽器應用程序。它可能無法與 Internet Explorer 或 Firefox 相比,但是 Swing 開發人員從此不再受到該庫對 Web 頁面和 HTML 可憐支持的制約,可以在任何應用程序中放心地依賴于完整 Web 支持 —— 即使顯示最困難的 Web 站點也可以。作為 JDIC 項目的靈感來源,WebBrowser
在正確的方向上開始發揮其作用。
SystemTray 組件
SystemTray
組件是最近才添加到 JDIC 中的。它允許 Java 應用程序把圖標放系統托盤上(在 Windows 中,是屏幕右下角包含音量圖標這類圖標的區域)。Windows 應用程序中一個不斷增長的趨勢就是把功能添加到系統托盤圖標上。即時通信應用程序就是一個很好的例子。它們常常只通過系統托盤圖標向用戶提供許多可以訪問的選項(例如關閉應用程序)。迄今為止,Java 應用程序還不能融入到這個潮流中。
像 JDIC 中的多數項目一樣,這個組件的 API 簡單易用。實際上,整個 org.jdesktop.jdic.tray
包只有兩個類:SystemTray
抽象了系統托盤本身;TrayIcon
抽象了系統托盤中的單個圖標。
請運行示例應用程序 —— demo.jdic.TrayDemoFrame
類 —— 觀察應用程序如何使用 JDIC 的系統托盤特性(請參閱 下載)。在運行應用程序時,應當在 Windows 的系統托盤上看到 yin-yang 圖標,就像圖 3 中左上角那樣。(在 Linux 和 Solaris 上,它的外觀當然會有所不同。即使在 Windows 上,也不完全與圖 3 中的相同,因為不可能得到系統托盤的菜單快照,所以這是一個重新制作的圖片。)
這個示例中有趣的部分不是 JFrame
本向,而是它如何處理與系統托盤的交互。請看一下示例應用程序中設置這部分的代碼。第一步是得到機器的系統托盤的實例:
|
接下來幾步是創建托盤圖標:
|
TrayIcon
類(很不幸)目前對它與鼠標單擊的交互方式進行了硬編碼。(JDIC 用戶正在呼吁修改這一點。) TrayIcon
在鼠標左鍵單擊時將觸發 ActionEvent
,而在鼠標右擊時則顯示彈出菜單。
最后,向系統托盤添加新的 TrayIcon
:
|
這就可以了 —— 已經創建了一個漂亮的系統托盤圖標,可以給 Java 應用程序提供一種非常本機的感覺了。
JDIC 項目最近向 TrayIcon
類添加了一個 displayMessage()
函數。它允許 TrayIcon
顯示 Windows 用戶熟悉的“泡泡消息”。單擊示例應用程序的 Alert 按鈕,就可以看到實際運用中的泡泡消息。以下是實現它的代碼:
|
本機文件支持
目前,Java 應用程序無法使用打開文件的默認應用程序。例如,Java 應用程序不能在 Microsoft Word 中打開 .doc。它不知道每臺機器上 Word 的路徑,所以,也就無法知道 Microsoft Word 是不是處理 .doc 文件的首選應用程序。而且也沒有可以從 Java 應用程序打印 .doc 文件的簡便方法。
JDIC 的 Desktop
類創建了一些簡單的靜態方法,允許 Java 應用程序與系統應用程序交互,從而解決了這些問題。系統應用程序構建到操作系統之中 —— 只有操作系統才知道哪個應用程序應該打開 .doc 文件。
這個組件不像 SystemTray
組件那么有用,但是確實彌補了一些空白。如果要處理不同的文件類型,例如文件瀏覽器,那么任何 Java 應用程序都可以使用 Desktop
類的方法:
可以在示例程序 demo.jdic.FileExtensionDemo
中看到這些函數的實際作用。應用程序頂部允許瀏覽查找文件,然后打開文件,如圖 4 所示:
在單擊 Open 按鈕時,Desktop
類將調用系統默認的 PDF 閱讀器,就像在下面的代碼中可以看到的那樣:
|
FileTypes 組件
目前 JDIC 項目的最后一部分是 FileTypes
。這個組件第一眼看起來可能不太重要,但是在我描述它之后,您就會看出它是創建整體 Java 桌面應用程序的非常重要的一個組成部分。FileType
解決的基本問題是:現有 Java 程序不能登記文件擴展名并把它們與應用程序關聯。在雙擊擴展名為 .doc 的文件時,Windows 會自然而然地知道要在 Word 中打開這個文件。Java 應用程序無法做到這點。無法編寫這樣的 Java 應用程序,讓它在雙擊具有新擴展名的文件時自動打開。也不能登記像“jexx”這樣的擴展名打開自己的 Java 應用程序。這對 Java 應用程序開發人員來說是一個嚴重的倒退,因為這讓會他們的應用程序感覺起來不像本機操作系統的一部分 —— 在用戶雙擊文件時,是希望他們不得不導航到 Open with... 對話框,還是希望他們打開應用程序呢?
org.jdesktop.jdic.filetypes
包中的三個類彌補了這個差距,它們允許 Java 應用程序登記文件擴展名,并把它們與 open、edit 和 print 動作關聯??梢赃x擇讓不同的應用程序進行打開和編輯。例如,應用程序可以用瀏覽器打開 XML 文件,并用文本編輯器編輯它。把動作連接到關聯之后,就可以把它登記到操作系統上。
現在開始研究 demo.jdic.FileExtensionDemo
類 (與前一節討論的 本機文件支持 是同一個應用程序)。 這次,將使用對話框的下半部分創建自己的 FileType
。圖 5 顯示了在填充了字段之后該示例看起來的樣子:
在單擊 Register 按鈕之后,可以在 Windows 文件夾選項對話框中打開 File Types 選項卡,查看剛才創建的內容,如圖 6 所示:
現在看一看示例應用程序中相關部分的代碼:
|
這個示例介紹了在操作系統中創建和登記文件類型有多簡單,Association
類中一些有趣的附加方法可以增強文件類型:
作為最后一步,為了顯示本機文件支持和 FileTypes
一起發揮作用的威力,請在桌面上創建叫做 example.jexx 的文件,如圖 7 所示:
現在,不需雙擊 example.jexx 文件(它什么也證明不了),請使用在 本機文件支持 中剛剛學到的 JDIC 代碼,通過 FileExtensionDemo
應用程序打開它。
在單擊 Open 按鈕時,會看到這個文件啟動了 Notepad。本機文件支持和 FileType
組件的結合是 Java 應用程序開發人員工具箱中的一個重要新增功能。對 Java 應用程序的可執行 JAR 文件實現本機支持雙擊的日子到來了?,F在用戶終于可以通過雙擊應用程序關聯的文件來打開 Java 應用程序了。這一個小小的但是獨特的新增特性讓 Java 應用程序看起來就像是操作系統天生的一部分一樣。
![]() |
|
孵化器中
迄今為止我描述的組件都已經很完善,并成為 JDIC 項目的有用部分。JDIC 還包含一組建設中的項目,叫做 孵化器 項目(也叫做沙箱)。在孵化器項目中可以發現許多完成程度,從已經完成的組件一直到等候進入 JDIC 包的條目,以及仍然是紙上設想的組件。
作為公開項目(公開想做貢獻的任何人的想法和努力成果)的一個組成部分,孵化器提供了一個促使新想法產生的測試機會。只有測試過而且 API 和功能得到批準的組件才會升級到最后發布的 JDIC 包。在閱讀這一節的孵化器組件時,要記住的一點是 —— 它們很酷,但是不完整。距離它們準備好登場可能還有幾個月的時間。
IconService
IconService
類執行單一的任務:把圖標名稱(通常采用難以理解的形式,例如 C:\Program Files\IBM\eclipse.exe,1) 轉換成 java.awt.Image
對象。一旦獲得了 Image
對象,就可以對其進行操作,所以可以操縱圖標本身。圖標名稱是通過調用 getIconFileName()
方法從另一個 JDIC 類得到的,這個類就是 Association
類。下面是把圖標轉換成 Image
對象的方法:
|
SystemInfo
SystemInfo
類試圖提供操作系統本身的信息。這包含諸如系統空閑時間、用戶會話是否鎖定之類的項目。在編寫這篇文章時,它提供的內容只有這些,沒有用來瀏覽或閱讀這些方法的 API。這個類好像仍然還處在嬰兒期,所以請耐心等待,看看是否會有更新。
FloatingDock
FloatingDock
類的目標是模擬 Windows 的任務欄,它既允許在上面添加組件,也允許把自己??吭谄聊坏哪硞€區域上。FloatingDock
基本上是個綁定到某個區域(左、右、下、上)的 JPanel
。它包含的功能大部分與 JPanel
相同,并且允許改變布局,添加和刪除組件。FloatingDock
還允許應用程序在任何時候改變區域,非常像把 Windows 的任務欄拖到屏幕上的新位置。
不要被誤導,以為 FloatingDock
提供了與任務欄一樣的功能。它只是支持??康侥硞€屏幕區域。如果想模擬任務欄、添加顯示 JToggleButton
的功能、改變它們的大小等,那么這些將完全取決于您自己。
下面展示了如何在屏幕底部創建 FloatingDock
對象并向它添加 JButton
:
|
Misc 包
Misc
孵化器包包含一個挑選出來的單任務組件集合。這些組件只包含一個或兩個靜態方法,試圖彌補 Java 到本機轉換的某個簡單差距。在編寫這篇文章時,這個包中的類只支持 Macintosh,因為開發人員感到在這個項目中 Mac 沒有得到應得的重視。目前,還沒有部署任何東西,因為項目還沒有為 Mac 完成一個構建。所以目前來說,最多只能閱讀它們的方法和它們能做什么,然后,期望在不遠的將來會發布一個發行版。
Volume
Misc
包的成員之一 Volume
類控制著計算機的音量。public float Volume.getInstance().getVolume()
得到當前音量,public void Volume.getInstance().setVolume(float vol)
設置音量。
這個類還允許用戶記錄音量上的變化,它提供了一個 addPropertyChangeListener()
函數,在計算機的音量發生變化時,該函數會通知對此感興趣的類 (但是不一定要通過 Volume
類本身)。
Wallpaper
Misc
包的另一個成員 Wallpaper
類及其對應的 WallpaperFactory
類允許 Java 應用程序改變操作系統的墻紙(桌面上顯示在背景中的圖片)。以下是改變墻紙的一些示例代碼:
|
Alerter
Misc
包的另一個成員 Alerter
類添補了一個很小的空白,它讓不在焦點的應用程序(例如,在其他窗口后面)通知用戶需要執行某些動作。在 Macs 上(也是目前支持這個類的地方),這個 Alert 會“彈回”??繄D標。在 Windows 上,在得到支持的時候,會閃動任務欄圖標,直到該圖標被選中。以下是一個代碼示例:
|
DockMenu
Misc
包中的最后一個類解決了??坎藛危―ock Menu),這個組件只在 Macs 中存在,在 Windows 或 Linux 系統中沒有對應的組件。DockMenu
類允許用戶把菜單附著到 Mac 應用程序的 Dock Menu 中。以下是如何使用 DockMenu
類的一個示例:
|
FileUtil
JDIC 孵化器的最新添加是 FileUtil
,這個類提供了一些新功能,補充了 JDK 中的 java.io.File
類。public java.math.BigInteger getFreeSpace(File dir)
方法返回目錄中的剩余空間,public boolean recycle(File f)
把文件放在操作系統的回收站,而不是刪除它。
![]() |
|
期望列表
JDIC 和孵化器中的組件列表相當詳盡,但是決不意味著彌補了 Java 應用程序和本機應用程序之間的所有差距。這一節是我和其他許多開發人員都想看到的 JDIC 中已實現的組件的期望列表。對于那些有想法的讀者來說,需要記住的是,JDIC 是一個開源項目,任何人在任何時候都可以對其做貢獻 —— 所以請放心地把這些想法付諸于行動吧。
本機支持的非矩形窗口
非矩形幀在應用程序中變得非常流行(例如,Microsoft 媒體播放器)。對跨多操作系統非矩形窗口的支持,Swing 開發人員對此已經呼吁了好多年。如果開發人員在 JDIC 中添加了對它的支持,那么整個 Swing 社區就會立即把它們捧上天。(現有解決方案中的方法包括來自 L2FProd.com 項目的只能用于 Windowsr 解決方案和我自己的 IFrame,這是一個“接近完成”的解決方案,請參閱 參考資料。)
桌面的“New”支持
當用戶在 Winows 桌面上右擊時,他們會看到 New 菜單選項,里面包含的子菜單中有用戶可以創建的常見文件類型。目前 Java 語言還不能訪問這個菜單。
特定文件的右擊支持
用戶在 Winows 中的文件上右擊時,會呈現對這個文件的選擇。有些應用程序會隨時自動地改變它們在這個選擇列表中的默認行為。(例如,請注意 WinZip,如果已經在機器上安裝該軟件的話,那么在右擊任何文件類型時,它會始終是其中的一個選擇。Java 語言無法永久地向這個菜單添加程序或選擇。
SystemInfo 類中的附加功能
SystemInfo
類中的附加功能可能很有用,其中包括支持查找進程名稱和編號、網絡狀態、網絡連接速度和電池使用壽命。
用戶和組管理
如果 Java 應用程序能夠管理操作系統的用戶和訪問組,包括處理口令管理,那會很棒。
時間和日期
如果讓 Java 程序可以改變操作系統的時間、日歷和時區,那會怎么樣?
![]() |
|
結束語
一般來說,JDIC 項目彌補了在 Swing 和 Java 程序語言之間的主要差距。隨著其他方面的不斷努力,差距會進一步縮小,總有一天,用戶會無法區分 Java 應用程序和本機應用程序。
已經看到,JDIC (在編寫這篇文章時)既包含成熟的、為生產作好準備的項目,又包含孵化器項目(包含不同開發階段的項目)。孵化器提供了一些有趣的項目,不久的將來,這些項目可能會走向成熟。重要的是要記?。喝绻麤Q定冒險在應用程序中包含孵化器項目,由于孵化器隨時可能會改變,可能會帶來一些問題,甚至可能使應用程序根本不工作。
原文轉自:http://www.anti-gravitydesign.com