文章詳情頁
駕馭“野馬”-- 探索Java SE 6的一些新特性
瀏覽:4日期:2024-06-16 18:29:18
內(nèi)容: 摘要這篇文章介紹了Mustang(野馬)——Sun Microsystems將在今年晚些時候正式發(fā)布的最新Java平臺。Jeff Friesen探討了Mustang有關(guān)控制臺輸入/輸出和分區(qū)空間的新方法、用于啟動畫面以及與系統(tǒng)托盤交互的新API。sun 將要在今年的晚些時候發(fā)布最新的Java平臺(開發(fā)代號Mustang)。作為正式的Java平臺,Standard Edition 6這個版本關(guān)注了幾個重要的主題,例如兼容性和穩(wěn)定性。有關(guān)完整的主題列表,參閱Java Specification Request 270,JSE 6的版本目錄。Mustang預(yù)期擁有的新特性包括(除了別的以外):· 一個編譯器API· 控制臺輸入/輸出(I/O)· 一個啟動畫面API· 眾多的Java 2D性能改進(jìn)· XML數(shù)字簽名· 一個系統(tǒng)托盤API· java.io.File類的分區(qū)空間方法· Java數(shù)據(jù)庫連接(JDBC)4.0· 公共注釋(Common annotations)· 腳本支持(Scripting)· 一個用于XML的流(streaming)API· 排序、過濾和加亮javax.swing.JTable內(nèi)容的能力· Javadoc標(biāo)記的更新· 可編程操作網(wǎng)絡(luò)屬性(例如廣播地址和子網(wǎng)掩碼)· 方便地打印javax.swing.text.JTextComponent的內(nèi)容的能力Mustang擁有遠(yuǎn)遠(yuǎn)超出一篇文章探討范圍的新特性,因此,本文只關(guān)注新特性的一小部份。確切地說,本文將討論用于控制臺輸入/輸出和分區(qū)空間的方法、用于啟動畫面以及與系統(tǒng)托盤交互的API。版權(quán)聲明:任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載時請務(wù)必保留以下作者信息和鏈接作者:Jeff Friesen;jlearner(作者的blog:http://blog.matrix.org.cn/page/jlearner)原文:http://www.javaworld.com/javaworld/jw-01-2006/jw-0109-mustang.htmltml譯文:http://www.matrix.org.cn/resource/article/44/44282_Mustang+Java+SE.html關(guān)鍵字:Mustang;Java SE 警告由于Mustang目前沒有最終發(fā)布,一些特性還可能會被改變或者去掉。所以,當(dāng)Sun公司最終發(fā)布Mustang的時候,本文中的一些代碼可能會需要改動或者變得完全不相干了。注意我使用Sun公司的Java 2 SDK版本1.6.0-rc (build 62)創(chuàng)建和測試了本文的代碼。底層平臺是Microsoft Windows ME。控制臺輸入/輸出在1997年5月,Sun收到了一個改進(jìn)控制臺輸入/輸出的增強(qiáng)請求(RFE)。申請人特別要求一種可以提示用戶輸入密碼并且允許用戶輸入密碼(任意長度)而不會在控制臺顯示出密碼字符的方法。申請人指出,抽象窗口工具包(AWT)的setEchoChar()方法并不合用,因?yàn)樗蕾囉贕UI的可用性,然而很多基于服務(wù)器的操作系統(tǒng)根本不使用GUI。在2005年后期,Sun回應(yīng)了RFE #4050435,為Mustang (build 57)添加了java.io.Console類。這個類所提供的方法可以訪問與當(dāng)前虛擬機(jī)相關(guān)聯(lián)的基于字符的控制臺設(shè)備。但是在調(diào)用這些方法之前,需要首先調(diào)用System的public static Console console()方法來獲取一個Console對象。該方法將返回一個用來與控制臺設(shè)備交互的Console對象,但是如果控制臺設(shè)備不存在就會返回null,例如當(dāng)你重定向標(biāo)準(zhǔn)輸入或標(biāo)準(zhǔn)輸出(或二者皆有)的時候。在調(diào)用System.console()來返回Console對象之后,下面的一段代碼將檢查返回的Console實(shí)例是否為null來測定控制臺設(shè)備是否存在:Console console = System.console ();if (console == null){ System.err.println ('Console not available'); return;}假設(shè)控制臺設(shè)備是存在的,你可以從控制臺輸入流讀取密碼和整行的字符,還可以向控制臺輸出流寫入字符。為了讀取密碼(而不會將密碼字符顯示到控制臺輸出流),你必須調(diào)用Console的兩個readPassword()方法之一。這兩個方法不允許換行符作為密碼的一部分,如果達(dá)到了控制臺輸入流的字符數(shù)目限制,他們將返回null。舉例來說,你可以調(diào)用public char [] readPassword(String fmt, Object... args)來提示用戶輸入密碼,其中提示是由java.util.Formatter-類型格式化字符串(fmt)和它的變量表(args)來描述的,然后從一個字符數(shù)組中返回用戶選擇的密碼。下面的代碼段反復(fù)調(diào)用readPassword(String fmt, Object... args)來提示用戶輸入密碼,直到用戶輸入了一個字符長度不小于MIN_PWD_LEN的密碼為止。char [] pwd;do{ pwd = console.readPassword ('Enter password (%d characters min):', MIN_PWD_LEN);}while (pwd.length < MIN_PWD_LEN);在密碼被存儲到pwd之后,就可以按需使用了。然而,出于安全性考慮,在不需要使用密碼的時候,應(yīng)該將pwd清零。除了readPassword()方法之外,Console提供了兩個readLine()方法以便于從控制臺讀取一整行的字符,并且將這些字符(不包括換行符)存儲在一個String中。如果達(dá)到了控制臺輸入流的字符數(shù)目限制,這兩個方法都將返回null。舉例來說,你可以在不提示用戶的情況下,調(diào)用public String readLine()來返回一行字符。下列代碼段演示了這個方法:關(guān)于兩個readPassword()方法和兩個readLine()方法有一些有趣的事。當(dāng)這些方法遇到輸入/輸出錯誤時,它們不拋出java.io.IOException對象(例如會被System.in.read()拋出),而是拋出一個java.io.IOError對象。由于IOError是Error的子類,你無需像捕捉IOException那樣來捕捉這個對象。向控制臺輸出流輸出字符的配套方法是public Console format(String fmt, Object... args)和作用相同的public Console printf(String fmt, Object... args)方法,后者內(nèi)部調(diào)用了format()。下列代碼段演示了printf():console.printf ('%s', input);輸出字符之后,format()——和printf()(按擴(kuò)展名)——自動轉(zhuǎn)儲清除控制臺輸出流。注意控制臺對象與唯一的一個java.io.Reader對象和唯一的一個java.io.PrintWriter對象相關(guān)聯(lián)。調(diào)用控制臺的public Reader reader()方法可以返回Reader。例如你可以把Reader傳遞給java.util.Scanner的一個構(gòu)造函數(shù)來對控制臺輸入流進(jìn)行復(fù)雜的解析。調(diào)用控制臺的public PrintWriter writer()方法可以獲取PrintWriter。然后你可以調(diào)用各種各樣有用的方法來輸出不同類型的數(shù)據(jù)到控制臺上。為方便起見,控制臺提供了一個public void flush()方法來調(diào)用PrinterWriter的flush()方法。讓我們用關(guān)于控制臺輸入/輸出的知識來做一個實(shí)際應(yīng)用——數(shù)據(jù)庫訪問。最終,我建立了一個Microsoft Access sales.mdb銷售數(shù)據(jù)庫,它隨著本文的代碼一同發(fā)布(可以在資源下載)。該數(shù)據(jù)庫包含一個單獨(dú)的territories表,它有兩列:Name代表售貨員的名字,Territory代表售貨員可以合法地出售產(chǎn)品的區(qū)域。我將下面的數(shù)據(jù)輸入到了數(shù)據(jù)庫中并且為它設(shè)置了密碼保護(hù)——密碼是mustang。| ------------------------ || Name | Territory || ------------------------ || John Doe | North | | Jane Doe | South | | Paul Smith | East || Kathy Smith | West || ------------------------ |銷售數(shù)據(jù)庫由一個Sales應(yīng)用軟件來訪問。在訪問數(shù)據(jù)庫之前,程序請求用戶輸入一個用戶名和密碼。然后它使用這些數(shù)據(jù)通過JDBC-ODBC bridge驅(qū)動來連接sales數(shù)據(jù)源(你可以用Windows控制面板的ODBC數(shù)據(jù)源小程序來創(chuàng)建它,用于識別sales.mdb的位置)。如果連接成功,程序?qū)⑤敵鰐erritories表的全部行和列的值。列表1顯示了Sales程序的源代碼。Listing 1. Sales.java // Sales.javaimport java.io.*;import java.sql.*;import java.util.*;class Sales{ public static void main (String [] args) throws ClassNotFoundException, SQLException { // Attempt to obtain a console. // 嘗試獲取控制臺 Console console = System.console (); if (console == null) { System.err.println ('sales: unable to obtain console'); return; } // Obtain username. // 獲取用戶名 String username = console.readLine ('Enter username: '); // Obtain password. // 獲取密碼 String password = new String (console.readPassword ('Enter password: ')); // Create a Vector datastructure for holding table records. // 建立一個向量數(shù)據(jù)結(jié)構(gòu)來存儲表記錄 Vector v = new Vector (); Connection con = null; Statement stmt = null; ResultSet rs; try { // Attempt to connect to the sales datasource. // 嘗試連接sales數(shù)據(jù)源 con = DriverManager.getConnection ('jdbc:odbc:sales', username, password); // Garbage collect the password—not a good idea to keep passwords // hanging around. // 對密碼進(jìn)行垃圾收集——始終留著密碼可不是個好主意 password = null; // Attempt to create a statement. // 嘗試建立一個statement stmt = con.createStatement (); // Establish the maximum number of rows that can be returned. // 設(shè)置允許返回的最大行數(shù) stmt.setMaxRows (10); // Attempt to fetch all rows from the territories table. // 嘗試讀取territories表的所有行 String query = 'SELECT * FROM territories'; rs = stmt.executeQuery (query); // Get number of columns. // 獲取列數(shù) int nCols = rs.getMetaData ().getColumnCount (); // Read all rows of all columns into storage. // 讀取所有列的每一行到向量存儲 int i = 0; while (rs.next ()) { Object [] buffer = new Object [nCols]; for (int j = 0; j < nCols; j++) buffer [j] = rs.getObject (j + 1); // NOTE: getObject requires a 1-based column index. // 注意:getObject要求列索引號從1開始 v.add (buffer); } // Extract rows from the array. // 從數(shù)組中取出全部行 Object [] rows = v.toArray (); for (i = 0; i < rows.length; i++) { // Extract columns from the row. // 取出一行中的每列值 Object [] cols = (Object []) rows [i]; // Print out the values from each column. // 顯示輸出每一列的值 for (int j = 0; j < cols.length; j++) console.printf ('%s ', cols [j]); console.printf ('n'); } console.printf ('Value at Row 1, Col 0 = %sn', getValue (v, 1, 0)); } catch (SQLException e) { console.printf ('sales: %sn', e.getMessage ()); } finally { if (stmt != null) try { stmt.close (); } catch (SQLException e2) {} if (con != null) try { con.close (); } catch (SQLException e2) {} } } static Object getValue (Vector v, int row, int col) { // The following conversion should really not be done in this method, // because it's inefficient. Placing the conversion here is a matter of // convenience. // 由于效率低下,下列的轉(zhuǎn)換其實(shí)本不該在這個方法中進(jìn)行,把轉(zhuǎn)換放在這里只是為了方便。 Object [] rows = v.toArray (); Object [] cols = (Object []) rows [row]; return cols [col]; }}編譯Sales.java然后執(zhí)行程序,首先呈現(xiàn)在你面的是Enter username:的提示。你可以隨意輸入任何用戶名,但至少要輸入點(diǎn)什么。接下來你將被提示輸入密碼,確定這里要使用mustang。假如連接成功建立了,你將會看到我在上面已經(jīng)展示的表值。列表1使用了Console的printf()方法來輸出表的內(nèi)容。然而,這種方法有一個不十分明顯的問題,如果territories表有很多行的數(shù)據(jù),在不滾動的情況下,并不是所有的數(shù)據(jù)都適合控制臺窗口的顯示。為了獲取這些行,通常需要重定向標(biāo)準(zhǔn)輸出到一個文件,但是如果你這樣做的話,System.console()將返回null,你也就無法使用控制臺輸入/輸出了。因此,在你的應(yīng)用中使用Console的printf()和format()方法之前要考慮清楚,不要使用它們向屏幕輸出大量的數(shù)據(jù),否則你可能就會無法看到全部數(shù)據(jù)了。注意 仔細(xì)地分析列表1的代碼,它并沒有通過Class.forName()來嘗試加載JDBC-ODBC bridge驅(qū)動。由于Mustang支持JDBC 4.0——它提供了一種內(nèi)在機(jī)制來使DriverManager定位和加載驅(qū)動類——你不再需要通過Class.forName()來顯式地加載驅(qū)動類了。盡管Console解決了最初的RFE問題,但是很多開發(fā)者都對這個類存在異議,主要的批評包括:· System.console()方法應(yīng)該被命名為System.getConsole()。然而一些不贊成的人爭辯說“get前綴只應(yīng)用在bean上面,而System并不是bean。此外,console()是一個靜態(tài)方法,這意味著IDE將不會認(rèn)為這個方法是用來獲取property的getter方法了。· Console類應(yīng)該提供不使用緩沖來讀取單個字符的能力。換句話說,程序不應(yīng)該等到用戶按下回車之后才能讀取用戶的輸入。一個類似C語言的kbhit()函數(shù)、通過返回一個Boolean值來判斷是否有按鍵被按下的方法將可以回應(yīng)這種批評,如果返回true,程序就可以調(diào)用另一個方法來返回下一個等待在BIOS按鍵緩沖中的按鍵了。· Console應(yīng)該提供打開/關(guān)閉控制臺字符顯示的能力。兩個類似C語言中g(shù)etch()函數(shù)(獲得字符而不在控制臺顯示,并且只當(dāng)沒有字符等待在BIOS按鍵緩沖中時才有效)和getche()函數(shù)(獲得字符同時在控制臺顯示,并且只當(dāng)沒有字符等待在BIOS按鍵緩沖中時才有效)的方法將可以回應(yīng)這種批評。· Console應(yīng)該提供清除屏幕的能力和其他可以在基于Unix的curses庫中找到的特性。· Console應(yīng)該提供一個detach()方法來將應(yīng)用程序從控制臺分離出來并且送入后臺。除了第一條之外,對Sun來說,在Mustang的正式版本中回應(yīng)上述批評的一部份(如果不是全部的話),也許還不是太晚。分區(qū)空間方法在收到改進(jìn)控制臺輸入/輸出的RFE #4050435的一個月之前,Sun收到了另外一個RFE,要求提供一種方法來得到可用的磁盤空間。Sun回應(yīng)了這個RFE #4057701,為File類加入了3個分區(qū)空間方法:· public long getFreeSpace():返回以抽象路徑名命名的分區(qū)的未分配空間字節(jié)數(shù)。 如果抽象路徑名不是磁盤分區(qū)的名字,返回值為空。· public long getTotalSpace():返回以抽象路徑名命名的分區(qū)的總磁盤空間。 如果抽象路徑名不是磁盤分區(qū)的名字,返回值為空public long getUsableSpace():返回以抽象路徑名命名的虛擬機(jī)可用的空間字節(jié)數(shù)。 如果抽象路徑名不是磁盤分區(qū)的名字,返回值為空. 對于Windows版本的Mustang,這些方法是按照Microsoft的GetDiskFreeSpaceEx函數(shù)實(shí)現(xiàn)的。讓我們基于這個函數(shù)的文檔重新定義一下這些方法:· getFreeSpace() 將返回當(dāng)前根目錄的磁盤的全部空閑字節(jié)數(shù),若當(dāng)前根目錄是一個CD-ROM驅(qū)動器則返回0. 如果有不可寫CD在一個CD-RW驅(qū)動器中會返回非0值。. · getTotalSpace()將返回與調(diào)用線程相關(guān)的用戶可用的磁盤字節(jié)總數(shù)。如果用戶配額被開啟,這個值可能會小于磁盤的空閑字節(jié)總數(shù)。getUsableSpace()將返回與調(diào)用線程相關(guān)的用戶可用的磁盤全部空閑字節(jié)數(shù)。如果用戶配額被開啟,這個值可能會小于磁盤的空閑字節(jié)總數(shù)。如果當(dāng)前根目錄是一個CD-ROM驅(qū)動器則返回0,如果有不可寫CD在一個CD-RW驅(qū)動器中會返回非0值。注意很多的現(xiàn)代操作系統(tǒng)允許限制每個用戶可用的最大磁盤空間。這個最大空間叫做用戶的配額,為用戶留出的磁盤空間區(qū)域叫做該用戶的分區(qū)。在這種情況下,getTotalSpace()返回的是與調(diào)用線程相關(guān)的用戶的配額。如果用戶沒有配額限制(只有一個用戶),該方法返回磁盤字節(jié)總數(shù)。同樣,getUsableSpace()返回的是與調(diào)用線程相關(guān)的用戶的配額限制內(nèi)的可用字節(jié)數(shù)。如果用戶沒有配額限制,該方法則返回磁盤的全部空閑字節(jié)數(shù)。最后,基于GetDiskFreeSpaceEx()的文檔,getFreeSpace()磁盤的空閑字節(jié)數(shù)——而不考慮用戶的配額。列表2展示了一個SpaceChecker程序的源代碼,它將顯示文件系統(tǒng)的每一個根目錄的空閑空間,以及分配給當(dāng)前用戶的可用空間和全部空間。Listing 2. SpaceChecker.java 列表 2. SpaceChecker.java // SpaceChecker.javaimport java.io.File;public class SpaceChecker{ public static void main (String [] args) { File [] roots = File.listRoots (); for (int i = 0; i < roots.length; i++) { System.out.println (roots [i]); System.out.println ('Free space = ' + roots [i].getFreeSpace ()); System.out.println ('Usable space = ' + roots [i].getUsableSpace ()); System.out.println ('Total space = ' + roots [i].getTotalSpace ()); System.out.println (); } }}在我的Windows ME平臺上運(yùn)行該程序時,我觀察到了下列信息:A:Free space = 0Usable space = 0Total space = 0C:Free space = 27913584640Usable space = 27913584640Total space = 40965373952M:Free space = 0Usable space = 0Total space = 0N:Free space = 0Usable space = 0Total space = 0由于磁盤配額沒有被應(yīng)用到Windows ME操作系統(tǒng)上,所以C:的空閑空間與可用空間是相同的。啟動畫面 API啟動畫面是基于GUI的現(xiàn)代應(yīng)用軟件的一個重要部分。啟動畫面不僅可以在漫長的軟件啟動過程中占據(jù)用戶的注意力(也可能用來通報用戶版本信息或者其他細(xì)節(jié)),還可以使用戶確定軟件正在啟動中。這在Java環(huán)境中是尤其重要的,因?yàn)镴VM需要一段時間來加載和啟動。圖1列舉了一個啟動畫面的例子。 圖1. 使用啟動畫面來顯示版權(quán)和其他重要信息Mustang對啟動畫面的實(shí)現(xiàn)是使用一個能夠顯示GIF(包括動畫GIF)、PNG或者JPEG圖像的無修飾窗口。Java應(yīng)用程序加載器創(chuàng)建一個啟動畫面窗口,然后響應(yīng)命令行參數(shù)或者JAR manifest入口,從而在窗口中顯示指定的圖片:· -splash命令行參數(shù)創(chuàng)建一個啟動畫面窗口并且顯示一個指定的圖片。例如,java -splash:mylogo.gif MyApp將創(chuàng)建啟動畫面窗口并且在這個窗口中顯示mylogo.gif 確定的圖像(見圖1),然后加載和啟動JVM,最后使JVM加載MyApp.class并且執(zhí)行該類的public static void main(String [] args)方法。· 由于你最有可能把重要的應(yīng)用打包進(jìn)一個jar文件, Mustang提供了一個SplashScreen-Image manifest項(xiàng)目,用來從jar文件的manifest中訪問啟動畫面的圖像。例如SplashScreen-Image:mylogo.gif把mylogo.gif識別為在啟動畫面窗口中顯示的圖像。假設(shè)下列信息被放置在了一個manifest文件中:Manifest-Version: 1.0Main-Class: MyAppSplashScreen-Image:mylogo.gif 將這個manifest文件、mylogo.gif和全部相關(guān)的類文件都打包進(jìn)myApp.jar,java -jar myApp.jar會在加載和啟動JVM及運(yùn)行應(yīng)用程序之前創(chuàng)建啟動畫面并且顯示mylogo.gif。如果你調(diào)用java -splash:yourlogo.gif -jar myApp.jar將會發(fā)生什么呢?在這種情況下,yourlogo.gif將會在啟動畫面窗口中出現(xiàn),因?yàn)槊钚袇?shù)-splash優(yōu)先替代了manifest設(shè)置SplashScreen-Image。假如你希望在圖像上加入視覺效果來定制啟動畫面,例如為一個有著漫長初始化過程的軟件的啟動畫面圖像加入一個動態(tài)的進(jìn)度條來告知用戶剩余的時間(參考“Mustang新的啟動畫面功能一文中的SplashTest程序)。Mustang的java.awt.SplashScreen類提供了對啟動畫面定制的支持。在沒有啟動畫面窗口的情況下,一個SplashScreen對象不具有任何意義,所以你不能從SplashScreen類實(shí)例化對象,而啟動畫面窗口只當(dāng)你指定了-splash命令行選項(xiàng)或者SplashScreen-Image manifest項(xiàng)目時才會存在。當(dāng)你指定了此命令行選項(xiàng)或者manifest項(xiàng)目并且窗口被創(chuàng)建出來,作為其啟動過程的一部分,Mustang會創(chuàng)建一個SplashScreen對象。調(diào)用SplashScreen的public static SplashScreen getSplashScreen()方法可以返回這個對象的一個實(shí)例。切記如果沒有啟動畫面窗口的話,將會返回null。在調(diào)用了SplashScreen.getSplashScreen()來返回SplashScreen對象之后,下力代碼段首先通過檢查返回的SplashScreen實(shí)例是否為null來測定啟動畫面窗口是否存在:SplashScreen ss = SplashScreen.getSplashScreen ();if (ss != null){ // Customize the splash screen.}假設(shè)啟動畫面窗口是存在的,你可以調(diào)用下列五種SplashScreen方法來獲取一個圖形環(huán)境,以便于在緩沖區(qū)繪制圖象、得到啟動畫面圖象、獲取圖象的尺寸、用其他圖象替換現(xiàn)有圖象或者是使用緩沖區(qū)中的內(nèi)容來更新啟動畫面窗口。· public Graphics getGraphics():以java.awt.image.BufferedImage的形式創(chuàng)建一個覆蓋圖象,它具有與啟動畫面圖象相同的尺寸,還有一個窗口,類型設(shè)置為BufferedImage.TYPE_INT_ARGB(給予圖象一個alpha通道來設(shè)置透明度),并且返回一個實(shí)例到BufferedImage的圖形環(huán)境。這幅圖象的所有像素都被設(shè)為黑色并且是完全透明的。你可以調(diào)用圖形環(huán)境的方法在BufferedImage中繪制。受到繪圖操作影響的每個像素都會被分配一個不透明的alpha值。如果在啟動畫面窗口關(guān)閉之后調(diào)用這個方法,它將會拋出IllegalStateException。· public URL getImageURL():以URL返回當(dāng)前的啟動畫面圖象。如果在啟動畫面窗口關(guān)閉之后調(diào)用這個方法,它將會拋出IllegalStateException。· public Dimension getSize():返回啟動畫面窗口的尺寸,同時也就是顯示的圖象的尺寸。如果在啟動畫面窗口關(guān)閉之后調(diào)用這個方法,它將會拋出IllegalStateException。· public void setImageURL(URL imageURL): 將啟動畫面圖象改為imageURL確定的圖象。當(dāng)圖象被加載、窗口被更新之后,該方法將返回。啟動畫面窗口將調(diào)整為圖象的同樣大小同時在屏幕上居中。如果imageURL為null,該方法將拋出NullPointerException;如果在啟動畫面窗口關(guān)閉之后調(diào)用這個方法,它將會拋出IllegalStateException。· public void update():更新啟動畫面窗口使得覆蓋圖內(nèi)容與當(dāng)前的啟動畫面窗口的像素相合成。由于采用了Source-over合成,覆蓋圖象的透明像素可以使啟動畫面圖象的像素顯示出來,而覆蓋圖象的不透明像素則遮擋了它下面啟動畫面圖象的像素。如果沒有調(diào)用getGraphics()來創(chuàng)建覆蓋圖象,或者在啟動畫面圖象關(guān)閉之后它才被調(diào)用,它將拋出IllegalStateException。列表3通過一個PhotoAlbum軟件的輪廓演示了getSplashScreen(),getGraphics(),getSize(),與update()這四個方法。這段程序定制了啟動畫面,在四周加上了一個紅色邊框,并且在水平中心顯示一條信息“Registering plug-ins...。Listing 3. PhotoAlbum.java 列表 3. PhotoAlbum.java // PhotoAlbum.javaimport java.awt.*;public class PhotoAlbum{ public static void main (String [] args) { SplashScreen ss = SplashScreen.getSplashScreen (); if (ss != null) { Graphics g = ss.getGraphics (); g.setColor (Color.red); // Color.white在我這個版本的Mustang中是默認(rèn)顏色 Dimension size = ss.getSize (); // 每個邊框?qū)挾榷际菆D象的寬和高中較小值的10% int borderSize; if (size.width < size.height) borderSize = (int) (size.width * 0.01); else borderSize = (int) (size.height * 0.01); for (int i = 0; i < borderSize; i++) g.drawRect (i, i, size.width-1-i*2, size.height-1-i*2); // 計算字符串在當(dāng)前字體時的寬和高 FontMetrics fm = g.getFontMetrics (); int strWidth = fm.stringWidth ('Registering plug-ins...'); int strHeight = fm.getHeight (); // 在字符串沒有超出啟動畫面窗口范圍時 if (strWidth < size.width && 4*strHeight < size.height) { g.setColor (Color.blue); g.drawString ('Registering plug-ins...', (size.width-strWidth)/2, size.height-4*strHeight); } // 拷貝覆蓋圖象到啟動畫面窗口 ss.update (); try { Thread.sleep (3000); // 暫停3秒鐘以便查看圖象 } catch (InterruptedException e) { } } }}為演示PhotoAlbum程序,隨本文的代碼一起,我加入了一張圖片palogo.jpg。當(dāng)你執(zhí)行java -splash:palogo.jpg PhotoAlbum之后,將首先在屏幕的中間看見palogo.jpg的圖象。在JVM完成載入并且開始運(yùn)行main(),你會看見如圖2所示的合成圖象(也是居中的)。 圖2. 標(biāo)識圖片改變了自身的邊框顏色,同時提示用戶正在注冊插件。點(diǎn)擊縮略圖以觀看全尺寸圖象。 當(dāng)?shù)谝粋€AWT或者Swing窗口變?yōu)榭梢姷臅r候,啟動畫面窗口會自動關(guān)閉,然而,也許你想要在軟件窗口出現(xiàn)之前就將其關(guān)閉,或者用你自己的窗口來替換它。SplashScreen類提供了以下3個方法來幫助你達(dá)到這個目的:· public void close():隱藏并關(guān)閉啟動畫面窗口,釋放分配給該窗口的全部資源。如果在啟動畫面窗口關(guān)閉之后調(diào)用這個方法,它將會拋出IllegalStateException。· public Rectangle getBounds():返回啟動畫面窗口的邊界。如果你調(diào)用setImageURL()創(chuàng)建了一個不同尺寸的新啟動畫面圖象,這些邊界將會改變。如果在啟動畫面窗口關(guān)閉之后調(diào)用這個方法,它將會拋出IllegalStateException。· public boolean isVisible():如果啟動畫面窗口是可見的,將返回一個Boolea值true,在窗口關(guān)閉之后調(diào)用則返回false。假如你用自己的窗口進(jìn)行了替換,你可以調(diào)用getBounds()來賦予它跟啟動畫面窗口同樣的初始坐標(biāo)和尺寸。此外,當(dāng)你自己的窗口變?yōu)榭梢姷臅r候,啟動畫面窗口將自動關(guān)閉。系統(tǒng)托盤API系統(tǒng)托盤是桌面上一個專門的區(qū)域,它顯示當(dāng)前的時間和常駐內(nèi)存的桌面應(yīng)用的圖標(biāo),并且被桌面上當(dāng)前運(yùn)行的所有應(yīng)用共享。表3展示了Windows ME的系統(tǒng)托盤,它位于Windows任務(wù)欄的右側(cè)。 表3. 系統(tǒng)托盤上的顯示屬性應(yīng)用程序圖標(biāo)相關(guān)聯(lián)的菜單和工具提示用戶只需要適當(dāng)?shù)剌p點(diǎn)鼠標(biāo),就隨時都可以與這些應(yīng)用進(jìn)行交互。例如,當(dāng)鼠標(biāo)位于應(yīng)用軟件的圖標(biāo)上時,雙擊鼠標(biāo)左鍵通常就可以打開應(yīng)用的主窗口(在Windows平臺上)。同樣地,把鼠標(biāo)移到應(yīng)用的圖標(biāo)上面并且單擊右鍵,通常就可以顯示特定應(yīng)用的彈出菜單。Mustang引入了類java.awt.SystemTray和java.awt.TrayIcon來與系統(tǒng)托盤進(jìn)行交互:SystemTray代表桌面的系統(tǒng)托盤,TrayIcon代表可以加入到系統(tǒng)托盤的一個圖標(biāo)。同SplashScreen一樣,你不能創(chuàng)建SystemTray對象,而是必須調(diào)用SystemTray的public static SystemTray getSystemTray()方法來返回一個代表系統(tǒng)托盤區(qū)域的SystemTray實(shí)例。由于在底層平臺不支持系統(tǒng)托盤時,該方法會拋出UnsupportedOperationException,所以你必須首先調(diào)用public static boolean isSupported()。如果系統(tǒng)托盤能得到最低限度的支持(除了顯示圖標(biāo)之外,最低限度的支持包括右鍵點(diǎn)擊圖標(biāo)時顯示的彈出式菜單,或者是左鍵雙擊圖標(biāo)時響應(yīng)的彈出事件),這個方法就將返回true,否則返回false。下列代碼段演示了獲取SystemTray實(shí)例的正確方式:if (SystemTray.isSupported ()){ SystemTray tray = SystemTray.getSystemTray (); // Do stuff with tray.}假設(shè)系統(tǒng)托盤可以被支持,你可以調(diào)用下列7個方法來實(shí)現(xiàn)各種各樣的功能:· public void add(TrayIcon trayIcon): 為SystemTray加入一個TrayIcon,在這之后,trayIcon所描述的圖標(biāo)將在系統(tǒng)托盤顯示出來。圖標(biāo)加入到系統(tǒng)托盤的順序取決于平臺的實(shí)現(xiàn)。同樣,當(dāng)應(yīng)用程序退出或者系統(tǒng)托盤變?yōu)椴豢捎玫臅r候,圖標(biāo)將被自動移除。如果trayIcon為null,該方法將拋出NullPointerException;如果你試圖多次添加同樣的TrayIcon實(shí)例,將拋出IllegalArgumentException;如果系統(tǒng)托盤不可用,將拋出AWTException。· public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener): 為trayIcons屬性加入一個java.beans.PropertyChangeListener到listener表,trayIcons屬性必須為propertyName的值。當(dāng)程序從系統(tǒng)托盤添加或者刪除一個TrayIcon或者圖標(biāo)被自動移除時,listener將被調(diào)用。該方法不拋出任何異常,即使propertyName或者listener為null。· public PropertyChangeListener [] getPropertyChangeListeners(String propertyName): 返回一個與指定屬性相關(guān)聯(lián)的PropertyChangeListener(對于當(dāng)前程序)的數(shù)組。目前只支持trayIcons,并且必須以propertyName值來指定。如果你傳遞了null或者任何其它值,該方法將返回一個空數(shù)組。· public TrayIcon [] getTrayIcons(): 返回含有被應(yīng)用程序加入到SystemTray 的全部TrayIcon的一個數(shù)組。所返回的數(shù)組是真實(shí)數(shù)組的一個拷貝,可以隨意修改而不會反映到系統(tǒng)托盤的圖標(biāo)上。如果沒有TrayIcon被加入,該方法將返回一個空數(shù)組。· public Dimension getTrayIconSize(): 以java.awt.Dimension對象的形式,返回圖標(biāo)出現(xiàn)在系統(tǒng)托盤時將占用的水平和垂直尺寸,其單位是像素。在創(chuàng)建圖標(biāo)之前調(diào)用該方法來決定圖標(biāo)的首選尺寸。這是TrayIcon的public Dimension getSize()方法的一種方便的實(shí)現(xiàn)。 · public void remove(TrayIcon trayIcon): 從SystemTray移除指定的TrayIcon。圖標(biāo)將從系統(tǒng)托盤移除,同時將通報所有的屬性改變listener。該方法不拋出任何異常,即使trayIcon為null。· public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener): 移除propertyName指定屬性的listener,propertyName必須是trayIcon(除此之外就沒有任何地方需要調(diào)用這個方法了)。該方法不拋出任何異常,即使propertyName或者listener為null。表4是一個用來演示上述方法的SystemTrayDemo1程序。這個程序先創(chuàng)建了一個內(nèi)部為實(shí)心紅色矩形的實(shí)心黃色圓形圖標(biāo),將這個圖標(biāo)添加到系統(tǒng)托盤,暫停3秒鐘,之后從系統(tǒng)托盤將其移除,再暫停3秒鐘,然后結(jié)束。表4. SystemTrayDemo1.java // SystemTrayDemo1.javaimport java.awt.*;import java.awt.image.*;import java.beans.*;public class SystemTrayDemo1{ public static void main (String [] args) { if (SystemTray.isSupported ()) { // 獲取系統(tǒng)托盤 SystemTray tray = SystemTray.getSystemTray (); // 注冊一個屬性變化listener來通知系統(tǒng)托盤上圖標(biāo)的添加和移除 PropertyChangeListener pcl; pcl = new PropertyChangeListener () { public void propertyChange (PropertyChangeEvent pce) { System.out.println ('Property changed = ' + pce.getPropertyName ()); System.out.println (); TrayIcon [] tia = (TrayIcon []) pce.getOldValue (); if (tia != null) { System.out.println ('Old tray icon array contents: '); for (int i = 0; i < tia.length; i++)System.out.println (tia [i]); System.out.println (); } tia = (TrayIcon []) pce.getNewValue (); if (tia != null) { System.out.println ('New tray icon array contents: '); for (int i = 0; i < tia.length; i++)System.out.println (tia [i]); System.out.println (); } } }; tray.addPropertyChangeListener ('trayIcons', pcl); // 為圖標(biāo)創(chuàng)建一個圖象 Dimension size = tray.getTrayIconSize (); BufferedImage bi = new BufferedImage (size.width, size.height, BufferedImage.TYPE_INT_RGB); Graphics g = bi.getGraphics (); g.setColor (Color.red); g.fillRect (0, 0, size.width, size.height); g.setColor (Color.yellow); int ovalSize = (size.width < size.height) ? size.width : size.height; ovalSize /= 2; g.fillOval (size.width/4, size.height/4, ovalSize, ovalSize); // 由該圖像創(chuàng)建一個圖標(biāo)并且將其添加到系統(tǒng)托盤。如果不能添加則結(jié)束程序。 TrayIcon icon = null; try { tray.add (icon = new TrayIcon (bi)); } catch (AWTException e) { System.out.println (e.getMessage ()); return; } // 暫停以便查看系統(tǒng)托盤 try { Thread.sleep (3000); } catch (InterruptedException e) { } // 從系統(tǒng)托盤移除圖標(biāo) tray.remove (icon); // 暫停以查看沒有了圖標(biāo)的系統(tǒng)托盤 try { Thread.sleep (3000); } catch (InterruptedException e) { } // 結(jié)束程序 System.exit (0); } }}在獲取了系統(tǒng)托盤實(shí)例之后,為這個實(shí)例注冊一個屬性改變listener,并且為圖標(biāo)創(chuàng)建一個java.awt.Image,表4基于這個圖標(biāo)創(chuàng)建了一個TrayIcon對象,然后將該對象加入到系統(tǒng)托盤。這個對象是通過調(diào)用TrayIcon's public TrayIcon(Image image)構(gòu)造器創(chuàng)建的。這個構(gòu)造器在TrayIcon對象中存儲了image。然后,當(dāng)tray.add (icon = new TrayIcon (bi));將TrayIcon加入到SystemTray的時候,這個image被取出并且顯示在系統(tǒng)托盤上。如果image為null,該構(gòu)造器和TrayIcon的另外兩個構(gòu)造器都拋出IllegalArgumentException。如果當(dāng)前平臺不支持系統(tǒng)托盤,這些構(gòu)造器將拋出UnsupportedOperationException。如果你在命令行運(yùn)行SystemTrayDemo1,你將會在系統(tǒng)托盤發(fā)現(xiàn)發(fā)現(xiàn)一個新圖標(biāo),在控制臺窗口將會獲得類似如下的輸出:Property changed = trayIconsOld tray icon array contents: New tray icon array contents: java.awt.TrayIcon@199f91cProperty changed = trayIconsOld tray icon array contents: java.awt.TrayIcon@199f91c幾分鐘之后,圖標(biāo)就會消失,SystemTrayDemo1程序結(jié)束,這對于持續(xù)運(yùn)行的應(yīng)用來說是不合適的。與此相反,你也許希望當(dāng)用戶右鍵點(diǎn)擊程序圖標(biāo)以彈出菜單,并且選擇了適當(dāng)?shù)捻?xiàng)目之后,程序才會結(jié)束。你可以用如下方式實(shí)現(xiàn)這個行為:創(chuàng)建一個java.awt.PopupMenu的實(shí)例,創(chuàng)立一個帶有動作 listener的菜單項(xiàng)目,使用戶選擇該項(xiàng)即可結(jié)束程序,然后將該菜單項(xiàng)加入到彈出菜單中,最后調(diào)用public TrayIcon(Image image, String tooltip, PopupMenu popup)構(gòu)造器使彈出菜單和圖標(biāo)相關(guān)聯(lián)。與圖標(biāo)的Image和相關(guān)聯(lián)的PopupMenu一起,你可以指定一個String來確定工具提示的文本內(nèi)容,當(dāng)鼠標(biāo)指針移動到圖標(biāo)上面時該文本就會出現(xiàn)。把null傳遞給tooltip就可以使它不再顯示。下列代碼段向系統(tǒng)托盤添加了一個帶有工具提示和彈出菜單的圖標(biāo):PopupMenu popup = new PopupMenu ();MenuItem miExit = new MenuItem ('Exit');ActionListener al;al = new ActionListener (){ public void actionPerformed (ActionEvent e) { System.out.println ('Goodbye'); System.exit (0); }};miExit.addActionListener (al);popup.add (miExit);TrayIcon ti = new TrayIcon (bi, 'System Tray Demo #2', popup);tray.add (ti); // Assume that tray was previously created. // 假定托盤在之前已經(jīng)被創(chuàng)建了當(dāng)用戶右鍵單擊鼠標(biāo)時彈出菜單就會出現(xiàn),然后用戶可以選擇菜單的Exit項(xiàng)目來執(zhí)行菜單項(xiàng)的動作listener,它就可以終止程序。除了鼠標(biāo)右鍵動作之外,你也許還希望當(dāng)用戶在圖標(biāo)上使用其它的鼠標(biāo)動作,例如雙擊。為了使程序響應(yīng)這些鼠標(biāo)動作,TrayIcon提供了下列注冊listener的方法:· public void addActionListener(ActionListener listener):為TrayIcon添加一個動作listener。當(dāng)用戶雙擊圖標(biāo)時,這個listener的public void actionPerformed(ActionEvent e)方法將被調(diào)用。你也許想要在多個TrayIcon之間共享一個動作listener,那么決定哪個圖標(biāo)響應(yīng)動作事件并且調(diào)用listener就變得很重要了。你可以通過TrayIcon 的public void setActionCommand(String command)方法來為其分配一個唯一的指令。然后你就可以在listener中調(diào)用java.awt.event.ActionEvent的public String getActionCommand()方法來返回指令名稱以及識別TrayIcon。為方便起見,TrayIcon也指定了一個public String getActionCommand()方法。調(diào)用TrayIcon的public void removeActionListener(ActionListener listener)方法從TrayIcon上移除listener。你也可以通過調(diào)用public ActionListener [] getActionListeners()方法來獲取一個含有全部注冊的動作listener的數(shù)組。· public void addMouseListener(MouseListener listener): 為TrayIcon添加一個鼠標(biāo)listener。當(dāng)鼠標(biāo)指針位于圖標(biāo)上方并且用戶按下、釋放、或者點(diǎn)擊鼠標(biāo)左鍵時,這個listener的各種方法(除了public void mouseEntered(MouseEvent e)和public void mouseExited(MouseEvent e)不被支持)將會被調(diào)用。如果你調(diào)用java.awt.event.MouseEvent從父類繼承的public Component getComponent()方法,你將得到一個null值。然而,MouseEvent從父類繼承的public Object getSource()方法將返回與事件相關(guān)聯(lián)的TrayIcon。調(diào)用MouseEvent的public int getX()和public int getY()方法可以得到鼠標(biāo)坐標(biāo)。這些坐標(biāo)是相對于屏幕的——而不是TrayIcon。調(diào)用TrayIcon's public void removeMouseListener(MouseListener listener)方法可以從TrayIcon中移除listener。通過調(diào)用public MouseListener [] getMouseListeners()可以獲取含有所有注冊的鼠標(biāo)listener的一個數(shù)組。· public void addMouseMotionListener(MouseMotionListener listener): 為TrayIcon添加一個鼠標(biāo)運(yùn)動listener。當(dāng)用戶在圖標(biāo)上移動鼠標(biāo)指針時,這個listener的public void mouseMoved(MouseEvent e)方法將被調(diào)用。(public void mouseDragged(MouseEvent e)方法不支持)再一次,getComponent()返回null,getSource()返回一個與事件相關(guān)聯(lián)的TrayIcon,getX()和getY()返回的坐標(biāo)是相對于屏幕的——而不是TrayIcon。調(diào)用TrayIcon的public void removeMouseMotionListener(MouseMotionListener listener)方法來從TrayIcon移除listener。你可以通過調(diào)用public MouseMotionListener [] getMouseMotionListeners()來得到一個含有全部注冊的鼠標(biāo)動作listener的數(shù)組。表5展示了一個擁有自己的String工具提示和PopupMenu的程序SystemTrayDemo2。該程序也調(diào)用了之前介紹的listener注冊方法來注冊用于響應(yīng)動作、鼠標(biāo)和鼠標(biāo)運(yùn)動事件的listener。表5. SystemTrayDemo2.java // SystemTrayDemo2.javaimport java.awt.*;import java.awt.event.*;import java.awt.image.*;import java.beans.*;public class SystemTrayDemo2{ public static void main (String [] args) { if (SystemTray.isSupported ()) { // 獲取系統(tǒng)托盤 SystemTray tray = SystemTray.getSystemTray (); // 為圖標(biāo)創(chuàng)建圖像 Dimension size = tray.getTrayIconSize (); BufferedImage bi = new BufferedImage (size.width, size.height, BufferedImage.TYPE_INT_RGB); Graphics g = bi.getGraphics (); g.setColor (Color.red); g.fillRect (0, 0, size.width, size.height); g.setColor (Color.yellow); int ovalSize = (size.width < size.height) ? size.width : size.height; ovalSize /= 2; g.fillOval (size.width/4, size.height/4, ovalSize, ovalSize); try { // 創(chuàng)建一個與程序的圖標(biāo)相關(guān)聯(lián)的彈出菜單。選擇菜單唯一的一個菜單項(xiàng)就會結(jié)束程序。 PopupMenu popup = new PopupMenu (); MenuItem miExit = new MenuItem ('Exit'); ActionListener al; al = new ActionListener () { public void actionPerformed (ActionEvent e) { System.out.println ('Goodbye'); System.exit (0); } }; miExit.addActionListener (al); popup.add (miExit); // 從圖像創(chuàng)建一個圖標(biāo),當(dāng)鼠標(biāo)位于圖標(biāo)上方式,選擇顯示一個工具提示,以及為圖標(biāo)分配彈出式菜單。 TrayIcon ti = new TrayIcon (bi, 'System Tray Demo #2', popup); // 創(chuàng)建并且關(guān)聯(lián)一個listener到圖標(biāo)上。當(dāng)你采用了適當(dāng)?shù)膭幼鳎缭赪indows下雙擊鼠標(biāo),actionPerformed()方法將會被調(diào)用。 al = new ActionListener () { public void actionPerformed (ActionEvent e) { System.out.println (e.getActionCommand ()); } }; ti.setActionCommand ('My Icon'); ti.addActionListener (al); // 創(chuàng)建并關(guān)聯(lián)一個鼠標(biāo)listener來記錄于圖標(biāo)相關(guān)聯(lián)的鼠標(biāo)事件 MouseListener ml; ml = new MouseListener () { public void mouseClicked (MouseEvent e) { System.out.println ('Tray icon: Mouse clicked'); } public void mouseEntered (MouseEvent e) { System.out.println ('Tray icon: Mouse entered'); } public void mouseExited (MouseEvent e) { System.out.println ('Tray icon: Mouse exited'); } public void mousePressed (MouseEvent e) { System.out.println ('Tray icon: Mouse pressed'); } public void mouseReleased (MouseEvent e) { System.out.println ('Tray icon: Mouse released'); } }; ti.addMouseListener (ml); //創(chuàng)建并關(guān)聯(lián)一個鼠標(biāo)運(yùn)動listener來記錄于圖標(biāo)相關(guān)聯(lián)的鼠標(biāo)運(yùn)動事件 MouseMotionListener mml; mml = new MouseMotionListener () { public void mouseDragged (MouseEvent e) { System.out.println ('Tray icon: Mouse dragged'); } public void mouseMoved (MouseEvent e) { System.out.println ('Tray icon: Mouse moved'); } }; ti.addMouseMotionListener (mml); // 將圖標(biāo)加入系統(tǒng)托盤 tray.add (ti); } catch (AWTException e) { System.out.println (e.getMessage ()); return; } } }}與SystemTrayDemo1同樣,SystemTrayDemo2在系統(tǒng)托盤顯示了同樣的圖標(biāo)。移動鼠標(biāo)到圖標(biāo)上,除了在控制臺窗口顯示信息“Mouse moved之外,工具提示也將會出現(xiàn)。當(dāng)鼠標(biāo)指針位于圖標(biāo)上方時,試一下左鍵單擊,各種按下、釋放、點(diǎn)擊消息將會在控制臺窗口出現(xiàn)。如果你雙擊圖標(biāo),動作指令的名字將會在控制臺窗口出現(xiàn)。最后,右鍵單擊圖標(biāo),你將會看見一個帶有Exit選項(xiàng)的彈出菜單。表4演示了SystemTrayDemo2的圖標(biāo)的兩個視圖。在左側(cè)你能看見圖標(biāo)上的工具提示,在右側(cè)你可以看見圖標(biāo)的彈出菜單。 表4. 托盤圖標(biāo)有自己的工具提示和彈出菜單TrayIcon類提供了額外的一些方法——其中一些是通過構(gòu)造器調(diào)用的——你也許會感興趣。這些方法包括:· public void displayMessage(String caption, String text, TrayIcon.MessageType messageType): 在系統(tǒng)托盤上圖標(biāo)附近顯示一條彈出消息。這條消息持續(xù)的時間依賴于平臺,之后便會消失。(我相信這個方法并不影響與TrayIcon相關(guān)聯(lián)的工具提示。)caption顯示在消息內(nèi)容text的上方,caption或text都可以為null,但是如果均為null,該方法將拋出NullPointerException。最后,messageType可以為下列消息類型之一:TrayIcon.MessageType.ERROR (錯誤消息), TrayIcon.MessageType.INFO (通知消息), TrayIcon.MessageType.NONE (簡單消息), or TrayIcon.MessageType.WARNING (警告消息)。當(dāng)消息出現(xiàn)時,平臺可以使用messageType來決定什么動作——顯示圖形還是發(fā)出聲音——需要被執(zhí)行。這個方法并不是所有的平臺都支持。例如,我在Windows ME平臺上就無法顯示消息。· public void setImage(Image image): 創(chuàng)建一個image作為TrayIcon的Image。這用于指示程序狀態(tài)的改變是非常方便的。前一個Image會丟棄而不調(diào)用Image的flush()方法——你必須明確的調(diào)用這個方法來轉(zhuǎn)儲所有被前一個Image對象使用的資源(包括為了屏幕繪制而緩存的像素數(shù)據(jù))。如果image為null,該方法將拋出NullPointerException。調(diào)用public Image getImage()方法來返回當(dāng)前的Image。· public void setImageAutoSize(boolean autosize): 設(shè)置TrayIcon的自動調(diào)整尺寸屬性。這個屬性決定了Image是否自動調(diào)整尺寸來適應(yīng)分配給系統(tǒng)托盤圖標(biāo)的空間。如果你傳遞true給autosize,Image將按照需要自動縮小或擴(kuò)大。否則,Image將被裁減以適應(yīng)分配的空間。調(diào)用public boolean isImageAutoSize()方法可以返回自動調(diào)整大小屬性的值。· public void setPopupMenu(PopupMenu popup): 為TrayIcon設(shè)置彈出菜單。如果popup為null,沒有PopupMenu與相關(guān)聯(lián)TrayIcon。如果你試圖為不同的TrayIcon設(shè)置同樣的彈出菜單,該方法將拋出IllegalArgumentException。一些平臺也許不支持彈出菜單,當(dāng)用戶右鍵單擊圖標(biāo)時,他們或者不顯示菜單,或者不顯示本地版本的菜單。調(diào)用public PopupMenu getPopupMenu()方法來返回當(dāng)前的PopupMenu。· public void setToolTip(String tooltip): 為TrayIcon設(shè)置工具提示。當(dāng)用戶把鼠標(biāo)移動到系統(tǒng)托盤上的圖標(biāo)上方時,工具提示會被顯示出來。傳遞null作為tooltip的值可以移除工具提示。工具提示在一些平臺上可能被簡化了。調(diào)用public String getToolTip()方法來返回當(dāng)前的工具提示String。在文章的結(jié)尾,我希望可以避開一個潛在的易混淆點(diǎn)。 關(guān)于isSupported()方法的SystemTray文檔建議“將默認(rèn)動作同時加入到動作listener和彈出菜單中以便保證托盤圖標(biāo)的默認(rèn)動作始終可用。這是什么意思呢?就是簡單地向PopupMenu添加一個Default菜單項(xiàng),它擁有與你關(guān)聯(lián)到TrayIcon的動作listener同樣的動作listener,像如下代碼段所示:PopupMenu popup = new PopupMenu ();MenuItem miDefault = new MenuItem ('Default');ActionListener alDefault;alDefault = new ActionListener () { public void actionPerformed (ActionEvent e) { System.out.println (e.getActionCommand ()); } };miDefault.addActionListener (alDefault);popup.add (miDefault); MenuItem miExit = new MenuItem ('Exit');ActionListener alExit;alExit = new ActionListener () { public void actionPerformed (ActionEvent e) { System.out.println ('Goodbye'); System.exit (0); } };miExit.addActionListener (alExit);popup.add (miExit);TrayIcon ti = new TrayIcon (bi, 'System Tray Demo #2', popup);ti.addActionListener (alDefault);結(jié)論Mustang就要到來了,你一定已經(jīng)忍不住想要在今年晚些時候正式版問世之前就體驗(yàn)一下這個最新的Java平臺。為了幫助你順利起步,本文展示了一些你也許可以在這個平臺上找到的小示例。本文關(guān)注了4個重要的新特性:控制臺輸入/輸出、分區(qū)空間方法、啟動畫面API和系統(tǒng)托盤API。Jeff Friesen是一個自由軟件開發(fā)者和教育者,擅長C、C++和Java技術(shù)。資源 · Matrix Java社區(qū):http://www.matrix.org.cn· 下載本文的代碼文件: http://www.javaworld.com/javaworld/jw-01-2006/mustang/jw-0109-mustang.zip · “創(chuàng)立與鞏固Java品牌 Jon Byous (Sun Developer Network, June 2005): http://java.sun.com/developer/technicalArticles/JavaOne2005/naming.html · 函數(shù) GetDiskFreeSpaceEx: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/getdiskfreespaceex.asp · JSR 270: Java SE 6 ('Mustang') 發(fā)行目錄: http://www.jcp.org/en/jsr/detail?id=270 · “Mustang新的啟動畫面功能 Oleg Semenov and Dana Nourie (Sun Developer Network, September 2005): http://java.sun.com/developer/technicalArticles/J2SE/Desktop/mustang/splashscreen/index.html · RFE #4050435: 不顯示字符的密碼輸入: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4050435 · RFE #4057701: 空閑磁盤空間方法: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4057701 Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd 摘要這篇文章介紹了Mustang(野馬?
標(biāo)簽:
Java
相關(guān)文章:
1. Django視圖類型總結(jié)2. Xml簡介_動力節(jié)點(diǎn)Java學(xué)院整理3. Intellij IDEA 關(guān)閉和開啟自動更新的提示?4. Ajax引擎 ajax請求步驟詳細(xì)代碼5. 解析原生JS getComputedStyle6. idea重置默認(rèn)配置的方法步驟7. IntelliJ IDEA Java項(xiàng)目手動添加依賴 jar 包的方法(圖解)8. Django使用HTTP協(xié)議向服務(wù)器傳參方式小結(jié)9. intellij idea設(shè)置統(tǒng)一JavaDoc模板的方法詳解10. Spring @Profile注解實(shí)現(xiàn)多環(huán)境配置
排行榜
