淺談Swing支持透明和不規(guī)則窗口
讓Swing支持透明和不規(guī)則窗口已經(jīng)成為 AWT 和 Swing 團(tuán)隊(duì)長久以來夢(mèng)寐以求的功能。盡管本機(jī)應(yīng)用程序在主要操作系統(tǒng)上使用這項(xiàng)功能已經(jīng)為時(shí)已久,但在核心 Java 中還不能使用它。即將發(fā)布的 “Consumer JRE”正在進(jìn)行修改,也就是對(duì) Java SE 6 進(jìn)行重大更新。Java SE 6 將為創(chuàng)建不規(guī)則、全透明和每個(gè)像素透明的***窗口提供 API.
歷史本機(jī)應(yīng)用程序的開發(fā)人員通常在開發(fā) UI 應(yīng)用程序中享受了更高級(jí)的靈活性。但是為此而付出的代價(jià)是將應(yīng)用程序限制在某一特定平臺(tái)上,在許多情況中,這種靈活性不如獲得更為豐富的 UI 體驗(yàn)和桌面緊密集成那么重要。從傳統(tǒng)上講,跨平臺(tái) UI 工具箱,例如 Swing、SWT、QT 和 wxWidgets 趨向于被動(dòng)應(yīng)付眾所周知的兩難問題。當(dāng)只有某些目標(biāo)平臺(tái)支持所要求的功能時(shí)怎么辦?在這種情況下,模擬缺失的功能可能只會(huì)讓您南轅北轍。
透明和不規(guī)則窗口是跨平臺(tái) UI 工具箱局限性的***例子。如果在特定目標(biāo)平臺(tái)不支持此項(xiàng)功能,那么在該平臺(tái)上就沒有什么更多事情要做了,此項(xiàng)功能可能用作強(qiáng)有力的參數(shù)向工具箱添加該項(xiàng)功能。但是,Swing 開發(fā)人員社區(qū)長久以來一直爭(zhēng)論主要目標(biāo)平臺(tái)不久就會(huì)提供這些功能。事實(shí)上,Windows 自從 Windows 95 (參見 MSDN 上的 SetWindowRgn 文檔 )就已經(jīng)支持不規(guī)則窗口了。在 X11 中匹配功能自從 1989 年 ( 參見 X Nonrectangular Window Shape Extension Library PDF 文檔 )就已經(jīng)可用了。在 OS X 中您僅能在 JFrame 上設(shè)置透明的背景顏色。
直到現(xiàn)在,對(duì)跨平臺(tái)透明和不規(guī)則窗口有興趣的 Swing支持應(yīng)用程序有三種主要可選方式。
在顯示目標(biāo)窗口之前使用 java.awt.Robot 捕獲桌面。這種方法在 Joshua Marinacci 和 Chris Adamson 編寫的 《 Swing Hacks 》 書中的 第 41 章 中已經(jīng)進(jìn)行了評(píng)述。
使用 JNI 包裝目標(biāo)平臺(tái)的本機(jī) API.使用由 Timothy Wall 開發(fā)的 JNA 庫。該庫在 2007 年問世,Timothy 對(duì)于 不規(guī)則窗口 和 字母掩碼透明度 已經(jīng)發(fā)表過博客。
***種方法的主要問題是要使用 Robot 類。即使您有權(quán)限獲得屏幕截圖,您也必須在顯示窗口之前完成。此外,如何保持桌面后臺(tái)同步?假設(shè)在后臺(tái)正在播放 YouTube 視頻。與窗口生成的事件不同( 調(diào)整大小,移動(dòng) ),AWT 并不在任何交叉窗口的重畫上提供注冊(cè)偵聽器的任何方式。雖然 Chris 和 Joshua 通過在至少每秒內(nèi)進(jìn)行快照提供解決方法,這對(duì)于覆蓋后臺(tái)視頻播放還不夠。而且在每次快照前需要對(duì)窗口加以隱藏;這可能導(dǎo)致可見的閃爍。
使用 JNI 和 JNA 導(dǎo)致顯著的視覺保真性改進(jìn)。純 JNI 會(huì)帶來開銷的急劇下降:您必須將目標(biāo)平臺(tái)的每一個(gè)相關(guān)的 API 綁定,還要捆綁本機(jī)庫。JNA 為您分擔(dān)這項(xiàng)重任; 它捆綁主機(jī)庫并提供能在運(yùn)行時(shí)提取并加載它們的類加載器。它支持 Linux、 OS X、 Windows、 Solaris 和 FreeBSD.
Consumer JRE Java SE 6 Update N, 通常稱作 Consumer JRE, 是 Sun 公司的努力成果,為重新配置 Java 將其作為開發(fā)富桌面應(yīng)用程序的可行方法。在 Consumer JRE 中的新功能和主要改進(jìn)列表相當(dāng)廣泛,并將特別閃耀的寶石隱藏在***一周構(gòu)建代碼之一的發(fā)行說明中。Bug 6633275 被簡(jiǎn)單地賦予“需要支持不規(guī)則/透明窗口”的標(biāo)題。但是該實(shí)現(xiàn)核心 JDK 新功能的可能性所帶給 Swing 開發(fā)人員的意義是深遠(yuǎn)的。本文的剩余部分將顯示能夠?qū)崿F(xiàn)和如何實(shí)現(xiàn)該功能的幾個(gè)示例。
在進(jìn)一步研究之前,有一個(gè)非常重要的注意事項(xiàng)。由于 Consumer JRE 被官方認(rèn)為是對(duì)穩(wěn)定 JDK 發(fā)行的一個(gè)次要更新,因此在“公共”包中不能添加任何新的 API( 類、方法等等 ),例如 java.awt 或 javax.swing. 在本文中討論的所有 API 在新 com.sun.awt.AWTUtilities 類中出現(xiàn),該類不是官方支持的部分 API.它在 Java SE 7 中的位置最有可能發(fā)生改變,簽名方法可能在現(xiàn)在和最終的 Consumer JRE 發(fā)行之間發(fā)生輕微變化。所以當(dāng)這種改變發(fā)生時(shí)準(zhǔn)備更改您自己的代碼。
AWTUtilities 類我首先討論 com.sun.awt.AWTUtilities 類,請(qǐng)參見Swing支持透明和不規(guī)則窗口 博客條目。
不規(guī)則的窗口看起來不是很好。窗口的邊緣呈鋸齒狀并且整體印象也不是很干凈。要獲得不規(guī)則窗口的更佳視覺效果,您必須使用 AWTUtilities.setWindowOpaque(Window, boolean) API,并使用柔性裁剪繪畫窗口背景。這在后續(xù)的 Swing 窗口的柔性裁剪和每像素透明度 博客條目中進(jìn)行了闡明。對(duì)于窗口的左上角和右上角,該條目采用 Chris Campbell 的 柔性裁剪教程 以及 Romain Guy 的 反射教程, 其中包括 Sebastien Petrucci 的改進(jìn)。
現(xiàn)在我們手頭上已經(jīng)有了這些 API,我們打算做些什么呢?對(duì)它們進(jìn)行探索這種可能性當(dāng)然是另人好奇的,我們正打算看看幾個(gè)多樣混合的示例。
工具提示讓我們使應(yīng)用工具提示變得透明怎么樣?對(duì)于輕量級(jí)工具提示,實(shí)現(xiàn)這一目標(biāo)是相當(dāng)容易的,因?yàn)樗鼈儽蛔鳛?Swing ***窗口的一部分加以繪畫。( 要獲得關(guān)于輕量級(jí)彈出菜單的詳細(xì)信息,請(qǐng)參見 玻璃窗格和輕量級(jí)彈出菜單條目。)但是,一旦工具提示成為重量級(jí)并“打破”窗口綁定,您必須繼續(xù)采用 Robot 或 JNI/JNA.現(xiàn)在讓我們看一看使用 AWTUtilities API 如何完成這項(xiàng)任務(wù)。
【編輯推薦】