国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

駕馭“野馬”-- 探索Java SE 6的一些新特性

瀏覽:5日期:2024-06-16 18:29:18
內(nèi)容: 摘要這篇文章介紹了Mustang(野馬)——Sun Microsystems將在今年晚些時(shí)候正式發(fā)布的最新Java平臺(tái)。Jeff Friesen探討了Mustang有關(guān)控制臺(tái)輸入/輸出和分區(qū)空間的新方法、用于啟動(dòng)畫面以及與系統(tǒng)托盤交互的新API。sun 將要在今年的晚些時(shí)候發(fā)布最新的Java平臺(tái)(開發(fā)代號(hào)Mustang)。作為正式的Java平臺(tái),Standard Edition 6這個(gè)版本關(guān)注了幾個(gè)重要的主題,例如兼容性和穩(wěn)定性。有關(guān)完整的主題列表,參閱Java Specification Request 270,JSE 6的版本目錄。Mustang預(yù)期擁有的新特性包括(除了別的以外):· 一個(gè)編譯器API· 控制臺(tái)輸入/輸出(I/O)· 一個(gè)啟動(dòng)畫面API· 眾多的Java 2D性能改進(jìn)· XML數(shù)字簽名· 一個(gè)系統(tǒng)托盤API· java.io.File類的分區(qū)空間方法· Java數(shù)據(jù)庫(kù)連接(JDBC)4.0· 公共注釋(Common annotations)· 腳本支持(Scripting)· 一個(gè)用于XML的流(streaming)API· 排序、過(guò)濾和加亮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)注新特性的一小部份。確切地說(shuō),本文將討論用于控制臺(tái)輸入/輸出和分區(qū)空間的方法、用于啟動(dòng)畫面以及與系統(tǒng)托盤交互的API。版權(quán)聲明:任何獲得Matrix授權(quán)的網(wǎng)站,轉(zhuǎn)載時(shí)請(qǐng)務(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目前沒(méi)有最終發(fā)布,一些特性還可能會(huì)被改變或者去掉。所以,當(dāng)Sun公司最終發(fā)布Mustang的時(shí)候,本文中的一些代碼可能會(huì)需要改動(dòng)或者變得完全不相干了。注意我使用Sun公司的Java 2 SDK版本1.6.0-rc (build 62)創(chuàng)建和測(cè)試了本文的代碼。底層平臺(tái)是Microsoft Windows ME。控制臺(tái)輸入/輸出在1997年5月,Sun收到了一個(gè)改進(jìn)控制臺(tái)輸入/輸出的增強(qiáng)請(qǐng)求(RFE)。申請(qǐng)人特別要求一種可以提示用戶輸入密碼并且允許用戶輸入密碼(任意長(zhǎng)度)而不會(huì)在控制臺(tái)顯示出密碼字符的方法。申請(qǐng)人指出,抽象窗口工具包(AWT)的setEchoChar()方法并不合用,因?yàn)樗蕾囉贕UI的可用性,然而很多基于服務(wù)器的操作系統(tǒng)根本不使用GUI。在2005年后期,Sun回應(yīng)了RFE #4050435,為Mustang (build 57)添加了java.io.Console類。這個(gè)類所提供的方法可以訪問(wèn)與當(dāng)前虛擬機(jī)相關(guān)聯(lián)的基于字符的控制臺(tái)設(shè)備。但是在調(diào)用這些方法之前,需要首先調(diào)用System的public static Console console()方法來(lái)獲取一個(gè)Console對(duì)象。該方法將返回一個(gè)用來(lái)與控制臺(tái)設(shè)備交互的Console對(duì)象,但是如果控制臺(tái)設(shè)備不存在就會(huì)返回null,例如當(dāng)你重定向標(biāo)準(zhǔn)輸入或標(biāo)準(zhǔn)輸出(或二者皆有)的時(shí)候。在調(diào)用System.console()來(lái)返回Console對(duì)象之后,下面的一段代碼將檢查返回的Console實(shí)例是否為null來(lái)測(cè)定控制臺(tái)設(shè)備是否存在:Console console = System.console ();if (console == null){ System.err.println ('Console not available'); return;}假設(shè)控制臺(tái)設(shè)備是存在的,你可以從控制臺(tái)輸入流讀取密碼和整行的字符,還可以向控制臺(tái)輸出流寫入字符。為了讀取密碼(而不會(huì)將密碼字符顯示到控制臺(tái)輸出流),你必須調(diào)用Console的兩個(gè)readPassword()方法之一。這兩個(gè)方法不允許換行符作為密碼的一部分,如果達(dá)到了控制臺(tái)輸入流的字符數(shù)目限制,他們將返回null。舉例來(lái)說(shuō),你可以調(diào)用public char [] readPassword(String fmt, Object... args)來(lái)提示用戶輸入密碼,其中提示是由java.util.Formatter-類型格式化字符串(fmt)和它的變量表(args)來(lái)描述的,然后從一個(gè)字符數(shù)組中返回用戶選擇的密碼。下面的代碼段反復(fù)調(diào)用readPassword(String fmt, Object... args)來(lái)提示用戶輸入密碼,直到用戶輸入了一個(gè)字符長(zhǎng)度不小于MIN_PWD_LEN的密碼為止。char [] pwd;do{ pwd = console.readPassword ('Enter password (%d characters min):', MIN_PWD_LEN);}while (pwd.length < MIN_PWD_LEN);在密碼被存儲(chǔ)到pwd之后,就可以按需使用了。然而,出于安全性考慮,在不需要使用密碼的時(shí)候,應(yīng)該將pwd清零。除了readPassword()方法之外,Console提供了兩個(gè)readLine()方法以便于從控制臺(tái)讀取一整行的字符,并且將這些字符(不包括換行符)存儲(chǔ)在一個(gè)String中。如果達(dá)到了控制臺(tái)輸入流的字符數(shù)目限制,這兩個(gè)方法都將返回null。舉例來(lái)說(shuō),你可以在不提示用戶的情況下,調(diào)用public String readLine()來(lái)返回一行字符。下列代碼段演示了這個(gè)方法:關(guān)于兩個(gè)readPassword()方法和兩個(gè)readLine()方法有一些有趣的事。當(dāng)這些方法遇到輸入/輸出錯(cuò)誤時(shí),它們不拋出java.io.IOException對(duì)象(例如會(huì)被System.in.read()拋出),而是拋出一個(gè)java.io.IOError對(duì)象。由于IOError是Error的子類,你無(wú)需像捕捉IOException那樣來(lái)捕捉這個(gè)對(duì)象。向控制臺(tái)輸出流輸出字符的配套方法是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ò)展名)——自動(dòng)轉(zhuǎn)儲(chǔ)清除控制臺(tái)輸出流。注意控制臺(tái)對(duì)象與唯一的一個(gè)java.io.Reader對(duì)象和唯一的一個(gè)java.io.PrintWriter對(duì)象相關(guān)聯(lián)。調(diào)用控制臺(tái)的public Reader reader()方法可以返回Reader。例如你可以把Reader傳遞給java.util.Scanner的一個(gè)構(gòu)造函數(shù)來(lái)對(duì)控制臺(tái)輸入流進(jìn)行復(fù)雜的解析。調(diào)用控制臺(tái)的public PrintWriter writer()方法可以獲取PrintWriter。然后你可以調(diào)用各種各樣有用的方法來(lái)輸出不同類型的數(shù)據(jù)到控制臺(tái)上。為方便起見,控制臺(tái)提供了一個(gè)public void flush()方法來(lái)調(diào)用PrinterWriter的flush()方法。讓我們用關(guān)于控制臺(tái)輸入/輸出的知識(shí)來(lái)做一個(gè)實(shí)際應(yīng)用——數(shù)據(jù)庫(kù)訪問(wèn)。最終,我建立了一個(gè)Microsoft Access sales.mdb銷售數(shù)據(jù)庫(kù),它隨著本文的代碼一同發(fā)布(可以在資源下載)。該數(shù)據(jù)庫(kù)包含一個(gè)單獨(dú)的territories表,它有兩列:Name代表售貨員的名字,Territory代表售貨員可以合法地出售產(chǎn)品的區(qū)域。我將下面的數(shù)據(jù)輸入到了數(shù)據(jù)庫(kù)中并且為它設(shè)置了密碼保護(hù)——密碼是mustang。| ------------------------ || Name | Territory || ------------------------ || John Doe | North | | Jane Doe | South | | Paul Smith | East || Kathy Smith | West || ------------------------ |銷售數(shù)據(jù)庫(kù)由一個(gè)Sales應(yīng)用軟件來(lái)訪問(wèn)。在訪問(wèn)數(shù)據(jù)庫(kù)之前,程序請(qǐng)求用戶輸入一個(gè)用戶名和密碼。然后它使用這些數(shù)據(jù)通過(guò)JDBC-ODBC bridge驅(qū)動(dòng)來(lái)連接sales數(shù)據(jù)源(你可以用Windows控制面板的ODBC數(shù)據(jù)源小程序來(lái)創(chuàng)建它,用于識(shí)別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. // 嘗試獲取控制臺(tái) 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. // 建立一個(gè)向量數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)表記錄 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. // 對(duì)密碼進(jìn)行垃圾收集——始終留著密碼可不是個(gè)好主意 password = null; // Attempt to create a statement. // 嘗試建立一個(gè)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. // 讀取所有列的每一行到向量存儲(chǔ) 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要求列索引號(hào)從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í)本不該在這個(gè)方法中進(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)什么。接下來(lái)你將被提示輸入密碼,確定這里要使用mustang。假如連接成功建立了,你將會(huì)看到我在上面已經(jīng)展示的表值。列表1使用了Console的printf()方法來(lái)輸出表的內(nèi)容。然而,這種方法有一個(gè)不十分明顯的問(wèn)題,如果territories表有很多行的數(shù)據(jù),在不滾動(dòng)的情況下,并不是所有的數(shù)據(jù)都適合控制臺(tái)窗口的顯示。為了獲取這些行,通常需要重定向標(biāo)準(zhǔn)輸出到一個(gè)文件,但是如果你這樣做的話,System.console()將返回null,你也就無(wú)法使用控制臺(tái)輸入/輸出了。因此,在你的應(yīng)用中使用Console的printf()和format()方法之前要考慮清楚,不要使用它們向屏幕輸出大量的數(shù)據(jù),否則你可能就會(huì)無(wú)法看到全部數(shù)據(jù)了。注意 仔細(xì)地分析列表1的代碼,它并沒(méi)有通過(guò)Class.forName()來(lái)嘗試加載JDBC-ODBC bridge驅(qū)動(dòng)。由于Mustang支持JDBC 4.0——它提供了一種內(nèi)在機(jī)制來(lái)使DriverManager定位和加載驅(qū)動(dòng)類——你不再需要通過(guò)Class.forName()來(lái)顯式地加載驅(qū)動(dòng)類了。盡管Console解決了最初的RFE問(wèn)題,但是很多開發(fā)者都對(duì)這個(gè)類存在異議,主要的批評(píng)包括:· System.console()方法應(yīng)該被命名為System.getConsole()。然而一些不贊成的人爭(zhēng)辯說(shuō)“get前綴只應(yīng)用在bean上面,而System并不是bean。此外,console()是一個(gè)靜態(tài)方法,這意味著IDE將不會(huì)認(rèn)為這個(gè)方法是用來(lái)獲取property的getter方法了。· Console類應(yīng)該提供不使用緩沖來(lái)讀取單個(gè)字符的能力。換句話說(shuō),程序不應(yīng)該等到用戶按下回車之后才能讀取用戶的輸入。一個(gè)類似C語(yǔ)言的kbhit()函數(shù)、通過(guò)返回一個(gè)Boolean值來(lái)判斷是否有按鍵被按下的方法將可以回應(yīng)這種批評(píng),如果返回true,程序就可以調(diào)用另一個(gè)方法來(lái)返回下一個(gè)等待在BIOS按鍵緩沖中的按鍵了。· Console應(yīng)該提供打開/關(guān)閉控制臺(tái)字符顯示的能力。兩個(gè)類似C語(yǔ)言中g(shù)etch()函數(shù)(獲得字符而不在控制臺(tái)顯示,并且只當(dāng)沒(méi)有字符等待在BIOS按鍵緩沖中時(shí)才有效)和getche()函數(shù)(獲得字符同時(shí)在控制臺(tái)顯示,并且只當(dāng)沒(méi)有字符等待在BIOS按鍵緩沖中時(shí)才有效)的方法將可以回應(yīng)這種批評(píng)。· Console應(yīng)該提供清除屏幕的能力和其他可以在基于Unix的curses庫(kù)中找到的特性。· Console應(yīng)該提供一個(gè)detach()方法來(lái)將應(yīng)用程序從控制臺(tái)分離出來(lái)并且送入后臺(tái)。除了第一條之外,對(duì)Sun來(lái)說(shuō),在Mustang的正式版本中回應(yīng)上述批評(píng)的一部份(如果不是全部的話),也許還不是太晚。分區(qū)空間方法在收到改進(jìn)控制臺(tái)輸入/輸出的RFE #4050435的一個(gè)月之前,Sun收到了另外一個(gè)RFE,要求提供一種方法來(lái)得到可用的磁盤空間。Sun回應(yīng)了這個(gè)RFE #4057701,為File類加入了3個(gè)分區(qū)空間方法:· public long getFreeSpace():返回以抽象路徑名命名的分區(qū)的未分配空間字節(jié)數(shù)。 如果抽象路徑名不是磁盤分區(qū)的名字,返回值為空。· public long getTotalSpace():返回以抽象路徑名命名的分區(qū)的總磁盤空間。 如果抽象路徑名不是磁盤分區(qū)的名字,返回值為空public long getUsableSpace():返回以抽象路徑名命名的虛擬機(jī)可用的空間字節(jié)數(shù)。 如果抽象路徑名不是磁盤分區(qū)的名字,返回值為空. 對(duì)于Windows版本的Mustang,這些方法是按照Microsoft的GetDiskFreeSpaceEx函數(shù)實(shí)現(xiàn)的。讓我們基于這個(gè)函數(shù)的文檔重新定義一下這些方法:· getFreeSpace() 將返回當(dāng)前根目錄的磁盤的全部空閑字節(jié)數(shù),若當(dāng)前根目錄是一個(gè)CD-ROM驅(qū)動(dòng)器則返回0. 如果有不可寫CD在一個(gè)CD-RW驅(qū)動(dòng)器中會(huì)返回非0值。. · getTotalSpace()將返回與調(diào)用線程相關(guān)的用戶可用的磁盤字節(jié)總數(shù)。如果用戶配額被開啟,這個(gè)值可能會(huì)小于磁盤的空閑字節(jié)總數(shù)。getUsableSpace()將返回與調(diào)用線程相關(guān)的用戶可用的磁盤全部空閑字節(jié)數(shù)。如果用戶配額被開啟,這個(gè)值可能會(huì)小于磁盤的空閑字節(jié)總數(shù)。如果當(dāng)前根目錄是一個(gè)CD-ROM驅(qū)動(dòng)器則返回0,如果有不可寫CD在一個(gè)CD-RW驅(qū)動(dòng)器中會(huì)返回非0值。注意很多的現(xiàn)代操作系統(tǒng)允許限制每個(gè)用戶可用的最大磁盤空間。這個(gè)最大空間叫做用戶的配額,為用戶留出的磁盤空間區(qū)域叫做該用戶的分區(qū)。在這種情況下,getTotalSpace()返回的是與調(diào)用線程相關(guān)的用戶的配額。如果用戶沒(méi)有配額限制(只有一個(gè)用戶),該方法返回磁盤字節(jié)總數(shù)。同樣,getUsableSpace()返回的是與調(diào)用線程相關(guān)的用戶的配額限制內(nèi)的可用字節(jié)數(shù)。如果用戶沒(méi)有配額限制,該方法則返回磁盤的全部空閑字節(jié)數(shù)。最后,基于GetDiskFreeSpaceEx()的文檔,getFreeSpace()磁盤的空閑字節(jié)數(shù)——而不考慮用戶的配額。列表2展示了一個(gè)SpaceChecker程序的源代碼,它將顯示文件系統(tǒng)的每一個(gè)根目錄的空閑空間,以及分配給當(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平臺(tái)上運(yùn)行該程序時(shí),我觀察到了下列信息: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由于磁盤配額沒(méi)有被應(yīng)用到Windows ME操作系統(tǒng)上,所以C:的空閑空間與可用空間是相同的。啟動(dòng)畫面 API啟動(dòng)畫面是基于GUI的現(xiàn)代應(yīng)用軟件的一個(gè)重要部分。啟動(dòng)畫面不僅可以在漫長(zhǎng)的軟件啟動(dòng)過(guò)程中占據(jù)用戶的注意力(也可能用來(lái)通報(bào)用戶版本信息或者其他細(xì)節(jié)),還可以使用戶確定軟件正在啟動(dòng)中。這在Java環(huán)境中是尤其重要的,因?yàn)镴VM需要一段時(shí)間來(lái)加載和啟動(dòng)。圖1列舉了一個(gè)啟動(dòng)畫面的例子。 圖1. 使用啟動(dòng)畫面來(lái)顯示版權(quán)和其他重要信息Mustang對(duì)啟動(dòng)畫面的實(shí)現(xiàn)是使用一個(gè)能夠顯示GIF(包括動(dòng)畫GIF)、PNG或者JPEG圖像的無(wú)修飾窗口。Java應(yīng)用程序加載器創(chuàng)建一個(gè)啟動(dòng)畫面窗口,然后響應(yīng)命令行參數(shù)或者JAR manifest入口,從而在窗口中顯示指定的圖片:· -splash命令行參數(shù)創(chuàng)建一個(gè)啟動(dòng)畫面窗口并且顯示一個(gè)指定的圖片。例如,java -splash:mylogo.gif MyApp將創(chuàng)建啟動(dòng)畫面窗口并且在這個(gè)窗口中顯示mylogo.gif 確定的圖像(見圖1),然后加載和啟動(dòng)JVM,最后使JVM加載MyApp.class并且執(zhí)行該類的public static void main(String [] args)方法。· 由于你最有可能把重要的應(yīng)用打包進(jìn)一個(gè)jar文件, Mustang提供了一個(gè)SplashScreen-Image manifest項(xiàng)目,用來(lái)從jar文件的manifest中訪問(wèn)啟動(dòng)畫面的圖像。例如SplashScreen-Image:mylogo.gif把mylogo.gif識(shí)別為在啟動(dòng)畫面窗口中顯示的圖像。假設(shè)下列信息被放置在了一個(gè)manifest文件中:Manifest-Version: 1.0Main-Class: MyAppSplashScreen-Image:mylogo.gif 將這個(gè)manifest文件、mylogo.gif和全部相關(guān)的類文件都打包進(jìn)myApp.jar,java -jar myApp.jar會(huì)在加載和啟動(dòng)JVM及運(yùn)行應(yīng)用程序之前創(chuàng)建啟動(dòng)畫面并且顯示mylogo.gif。如果你調(diào)用java -splash:yourlogo.gif -jar myApp.jar將會(huì)發(fā)生什么呢?在這種情況下,yourlogo.gif將會(huì)在啟動(dòng)畫面窗口中出現(xiàn),因?yàn)槊钚袇?shù)-splash優(yōu)先替代了manifest設(shè)置SplashScreen-Image。假如你希望在圖像上加入視覺(jué)效果來(lái)定制啟動(dòng)畫面,例如為一個(gè)有著漫長(zhǎng)初始化過(guò)程的軟件的啟動(dòng)畫面圖像加入一個(gè)動(dòng)態(tài)的進(jìn)度條來(lái)告知用戶剩余的時(shí)間(參考“Mustang新的啟動(dòng)畫面功能一文中的SplashTest程序)。Mustang的java.awt.SplashScreen類提供了對(duì)啟動(dòng)畫面定制的支持。在沒(méi)有啟動(dòng)畫面窗口的情況下,一個(gè)SplashScreen對(duì)象不具有任何意義,所以你不能從SplashScreen類實(shí)例化對(duì)象,而啟動(dòng)畫面窗口只當(dāng)你指定了-splash命令行選項(xiàng)或者SplashScreen-Image manifest項(xiàng)目時(shí)才會(huì)存在。當(dāng)你指定了此命令行選項(xiàng)或者manifest項(xiàng)目并且窗口被創(chuàng)建出來(lái),作為其啟動(dòng)過(guò)程的一部分,Mustang會(huì)創(chuàng)建一個(gè)SplashScreen對(duì)象。調(diào)用SplashScreen的public static SplashScreen getSplashScreen()方法可以返回這個(gè)對(duì)象的一個(gè)實(shí)例。切記如果沒(méi)有啟動(dòng)畫面窗口的話,將會(huì)返回null。在調(diào)用了SplashScreen.getSplashScreen()來(lái)返回SplashScreen對(duì)象之后,下力代碼段首先通過(guò)檢查返回的SplashScreen實(shí)例是否為null來(lái)測(cè)定啟動(dòng)畫面窗口是否存在:SplashScreen ss = SplashScreen.getSplashScreen ();if (ss != null){ // Customize the splash screen.}假設(shè)啟動(dòng)畫面窗口是存在的,你可以調(diào)用下列五種SplashScreen方法來(lái)獲取一個(gè)圖形環(huán)境,以便于在緩沖區(qū)繪制圖象、得到啟動(dòng)畫面圖象、獲取圖象的尺寸、用其他圖象替換現(xiàn)有圖象或者是使用緩沖區(qū)中的內(nèi)容來(lái)更新啟動(dòng)畫面窗口。· public Graphics getGraphics():以java.awt.image.BufferedImage的形式創(chuàng)建一個(gè)覆蓋圖象,它具有與啟動(dòng)畫面圖象相同的尺寸,還有一個(gè)窗口,類型設(shè)置為BufferedImage.TYPE_INT_ARGB(給予圖象一個(gè)alpha通道來(lái)設(shè)置透明度),并且返回一個(gè)實(shí)例到BufferedImage的圖形環(huán)境。這幅圖象的所有像素都被設(shè)為黑色并且是完全透明的。你可以調(diào)用圖形環(huán)境的方法在BufferedImage中繪制。受到繪圖操作影響的每個(gè)像素都會(huì)被分配一個(gè)不透明的alpha值。如果在啟動(dòng)畫面窗口關(guān)閉之后調(diào)用這個(gè)方法,它將會(huì)拋出IllegalStateException。· public URL getImageURL():以URL返回當(dāng)前的啟動(dòng)畫面圖象。如果在啟動(dòng)畫面窗口關(guān)閉之后調(diào)用這個(gè)方法,它將會(huì)拋出IllegalStateException。· public Dimension getSize():返回啟動(dòng)畫面窗口的尺寸,同時(shí)也就是顯示的圖象的尺寸。如果在啟動(dòng)畫面窗口關(guān)閉之后調(diào)用這個(gè)方法,它將會(huì)拋出IllegalStateException。· public void setImageURL(URL imageURL): 將啟動(dòng)畫面圖象改為imageURL確定的圖象。當(dāng)圖象被加載、窗口被更新之后,該方法將返回。啟動(dòng)畫面窗口將調(diào)整為圖象的同樣大小同時(shí)在屏幕上居中。如果imageURL為null,該方法將拋出NullPointerException;如果在啟動(dòng)畫面窗口關(guān)閉之后調(diào)用這個(gè)方法,它將會(huì)拋出IllegalStateException。· public void update():更新啟動(dòng)畫面窗口使得覆蓋圖內(nèi)容與當(dāng)前的啟動(dòng)畫面窗口的像素相合成。由于采用了Source-over合成,覆蓋圖象的透明像素可以使啟動(dòng)畫面圖象的像素顯示出來(lái),而覆蓋圖象的不透明像素則遮擋了它下面啟動(dòng)畫面圖象的像素。如果沒(méi)有調(diào)用getGraphics()來(lái)創(chuàng)建覆蓋圖象,或者在啟動(dòng)畫面圖象關(guān)閉之后它才被調(diào)用,它將拋出IllegalStateException。列表3通過(guò)一個(gè)PhotoAlbum軟件的輪廓演示了getSplashScreen(),getGraphics(),getSize(),與update()這四個(gè)方法。這段程序定制了啟動(dòng)畫面,在四周加上了一個(gè)紅色邊框,并且在水平中心顯示一條信息“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在我這個(gè)版本的Mustang中是默認(rèn)顏色 Dimension size = ss.getSize (); // 每個(gè)邊框?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); // 計(jì)算字符串在當(dāng)前字體時(shí)的寬和高 FontMetrics fm = g.getFontMetrics (); int strWidth = fm.stringWidth ('Registering plug-ins...'); int strHeight = fm.getHeight (); // 在字符串沒(méi)有超出啟動(dòng)畫面窗口范圍時(shí) 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); } // 拷貝覆蓋圖象到啟動(dòng)畫面窗口 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(),你會(huì)看見如圖2所示的合成圖象(也是居中的)。 圖2. 標(biāo)識(shí)圖片改變了自身的邊框顏色,同時(shí)提示用戶正在注冊(cè)插件。點(diǎn)擊縮略圖以觀看全尺寸圖象。 當(dāng)?shù)谝粋€(gè)AWT或者Swing窗口變?yōu)榭梢姷臅r(shí)候,啟動(dòng)畫面窗口會(huì)自動(dòng)關(guān)閉,然而,也許你想要在軟件窗口出現(xiàn)之前就將其關(guān)閉,或者用你自己的窗口來(lái)替換它。SplashScreen類提供了以下3個(gè)方法來(lái)幫助你達(dá)到這個(gè)目的:· public void close():隱藏并關(guān)閉啟動(dòng)畫面窗口,釋放分配給該窗口的全部資源。如果在啟動(dòng)畫面窗口關(guān)閉之后調(diào)用這個(gè)方法,它將會(huì)拋出IllegalStateException。· public Rectangle getBounds():返回啟動(dòng)畫面窗口的邊界。如果你調(diào)用setImageURL()創(chuàng)建了一個(gè)不同尺寸的新啟動(dòng)畫面圖象,這些邊界將會(huì)改變。如果在啟動(dòng)畫面窗口關(guān)閉之后調(diào)用這個(gè)方法,它將會(huì)拋出IllegalStateException。· public boolean isVisible():如果啟動(dòng)畫面窗口是可見的,將返回一個(gè)Boolea值true,在窗口關(guān)閉之后調(diào)用則返回false。假如你用自己的窗口進(jìn)行了替換,你可以調(diào)用getBounds()來(lái)賦予它跟啟動(dòng)畫面窗口同樣的初始坐標(biāo)和尺寸。此外,當(dāng)你自己的窗口變?yōu)榭梢姷臅r(shí)候,啟動(dòng)畫面窗口將自動(dòng)關(guān)閉。系統(tǒng)托盤API系統(tǒng)托盤是桌面上一個(gè)專門的區(qū)域,它顯示當(dāng)前的時(shí)間和常駐內(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),就隨時(shí)都可以與這些應(yīng)用進(jìn)行交互。例如,當(dāng)鼠標(biāo)位于應(yīng)用軟件的圖標(biāo)上時(shí),雙擊鼠標(biāo)左鍵通常就可以打開應(yīng)用的主窗口(在Windows平臺(tái)上)。同樣地,把鼠標(biāo)移到應(yīng)用的圖標(biāo)上面并且單擊右鍵,通常就可以顯示特定應(yīng)用的彈出菜單。Mustang引入了類java.awt.SystemTray和java.awt.TrayIcon來(lái)與系統(tǒng)托盤進(jìn)行交互:SystemTray代表桌面的系統(tǒng)托盤,TrayIcon代表可以加入到系統(tǒng)托盤的一個(gè)圖標(biāo)。同SplashScreen一樣,你不能創(chuàng)建SystemTray對(duì)象,而是必須調(diào)用SystemTray的public static SystemTray getSystemTray()方法來(lái)返回一個(gè)代表系統(tǒng)托盤區(qū)域的SystemTray實(shí)例。由于在底層平臺(tái)不支持系統(tǒng)托盤時(shí),該方法會(huì)拋出UnsupportedOperationException,所以你必須首先調(diào)用public static boolean isSupported()。如果系統(tǒng)托盤能得到最低限度的支持(除了顯示圖標(biāo)之外,最低限度的支持包括右鍵點(diǎn)擊圖標(biāo)時(shí)顯示的彈出式菜單,或者是左鍵雙擊圖標(biāo)時(shí)響應(yīng)的彈出事件),這個(gè)方法就將返回true,否則返回false。下列代碼段演示了獲取SystemTray實(shí)例的正確方式:if (SystemTray.isSupported ()){ SystemTray tray = SystemTray.getSystemTray (); // Do stuff with tray.}假設(shè)系統(tǒng)托盤可以被支持,你可以調(diào)用下列7個(gè)方法來(lái)實(shí)現(xiàn)各種各樣的功能:· public void add(TrayIcon trayIcon): 為SystemTray加入一個(gè)TrayIcon,在這之后,trayIcon所描述的圖標(biāo)將在系統(tǒng)托盤顯示出來(lái)。圖標(biāo)加入到系統(tǒng)托盤的順序取決于平臺(tái)的實(shí)現(xiàn)。同樣,當(dāng)應(yīng)用程序退出或者系統(tǒng)托盤變?yōu)椴豢捎玫臅r(shí)候,圖標(biāo)將被自動(dòng)移除。如果trayIcon為null,該方法將拋出NullPointerException;如果你試圖多次添加同樣的TrayIcon實(shí)例,將拋出IllegalArgumentException;如果系統(tǒng)托盤不可用,將拋出AWTException。· public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener): 為trayIcons屬性加入一個(gè)java.beans.PropertyChangeListener到listener表,trayIcons屬性必須為propertyName的值。當(dāng)程序從系統(tǒng)托盤添加或者刪除一個(gè)TrayIcon或者圖標(biāo)被自動(dòng)移除時(shí),listener將被調(diào)用。該方法不拋出任何異常,即使propertyName或者listener為null。· public PropertyChangeListener [] getPropertyChangeListeners(String propertyName): 返回一個(gè)與指定屬性相關(guān)聯(lián)的PropertyChangeListener(對(duì)于當(dāng)前程序)的數(shù)組。目前只支持trayIcons,并且必須以propertyName值來(lái)指定。如果你傳遞了null或者任何其它值,該方法將返回一個(gè)空數(shù)組。· public TrayIcon [] getTrayIcons(): 返回含有被應(yīng)用程序加入到SystemTray 的全部TrayIcon的一個(gè)數(shù)組。所返回的數(shù)組是真實(shí)數(shù)組的一個(gè)拷貝,可以隨意修改而不會(huì)反映到系統(tǒng)托盤的圖標(biāo)上。如果沒(méi)有TrayIcon被加入,該方法將返回一個(gè)空數(shù)組。· public Dimension getTrayIconSize(): 以java.awt.Dimension對(duì)象的形式,返回圖標(biāo)出現(xiàn)在系統(tǒng)托盤時(shí)將占用的水平和垂直尺寸,其單位是像素。在創(chuàng)建圖標(biāo)之前調(diào)用該方法來(lái)決定圖標(biāo)的首選尺寸。這是TrayIcon的public Dimension getSize()方法的一種方便的實(shí)現(xiàn)。 · public void remove(TrayIcon trayIcon): 從SystemTray移除指定的TrayIcon。圖標(biāo)將從系統(tǒng)托盤移除,同時(shí)將通報(bào)所有的屬性改變listener。該方法不拋出任何異常,即使trayIcon為null。· public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener): 移除propertyName指定屬性的listener,propertyName必須是trayIcon(除此之外就沒(méi)有任何地方需要調(diào)用這個(gè)方法了)。該方法不拋出任何異常,即使propertyName或者listener為null。表4是一個(gè)用來(lái)演示上述方法的SystemTrayDemo1程序。這個(gè)程序先創(chuàng)建了一個(gè)內(nèi)部為實(shí)心紅色矩形的實(shí)心黃色圓形圖標(biāo),將這個(gè)圖標(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 (); // 注冊(cè)一個(gè)屬性變化listener來(lái)通知系統(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)建一個(gè)圖象 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)建一個(gè)圖標(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); // 暫停以查看沒(méi)有了圖標(biāo)的系統(tǒng)托盤 try { Thread.sleep (3000); } catch (InterruptedException e) { } // 結(jié)束程序 System.exit (0); } }}在獲取了系統(tǒng)托盤實(shí)例之后,為這個(gè)實(shí)例注冊(cè)一個(gè)屬性改變listener,并且為圖標(biāo)創(chuàng)建一個(gè)java.awt.Image,表4基于這個(gè)圖標(biāo)創(chuàng)建了一個(gè)TrayIcon對(duì)象,然后將該對(duì)象加入到系統(tǒng)托盤。這個(gè)對(duì)象是通過(guò)調(diào)用TrayIcon's public TrayIcon(Image image)構(gòu)造器創(chuàng)建的。這個(gè)構(gòu)造器在TrayIcon對(duì)象中存儲(chǔ)了image。然后,當(dāng)tray.add (icon = new TrayIcon (bi));將TrayIcon加入到SystemTray的時(shí)候,這個(gè)image被取出并且顯示在系統(tǒng)托盤上。如果image為null,該構(gòu)造器和TrayIcon的另外兩個(gè)構(gòu)造器都拋出IllegalArgumentException。如果當(dāng)前平臺(tái)不支持系統(tǒng)托盤,這些構(gòu)造器將拋出UnsupportedOperationException。如果你在命令行運(yùn)行SystemTrayDemo1,你將會(huì)在系統(tǒng)托盤發(fā)現(xiàn)發(fā)現(xiàn)一個(gè)新圖標(biāo),在控制臺(tái)窗口將會(huì)獲得類似如下的輸出: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)就會(huì)消失,SystemTrayDemo1程序結(jié)束,這對(duì)于持續(xù)運(yùn)行的應(yīng)用來(lái)說(shuō)是不合適的。與此相反,你也許希望當(dāng)用戶右鍵點(diǎn)擊程序圖標(biāo)以彈出菜單,并且選擇了適當(dāng)?shù)捻?xiàng)目之后,程序才會(huì)結(jié)束。你可以用如下方式實(shí)現(xiàn)這個(gè)行為:創(chuàng)建一個(gè)java.awt.PopupMenu的實(shí)例,創(chuàng)立一個(gè)帶有動(dò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一起,你可以指定一個(gè)String來(lái)確定工具提示的文本內(nèi)容,當(dāng)鼠標(biāo)指針移動(dòng)到圖標(biāo)上面時(shí)該文本就會(huì)出現(xiàn)。把null傳遞給tooltip就可以使它不再顯示。下列代碼段向系統(tǒng)托盤添加了一個(gè)帶有工具提示和彈出菜單的圖標(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)時(shí)彈出菜單就會(huì)出現(xiàn),然后用戶可以選擇菜單的Exit項(xiàng)目來(lái)執(zhí)行菜單項(xiàng)的動(dòng)作listener,它就可以終止程序。除了鼠標(biāo)右鍵動(dòng)作之外,你也許還希望當(dāng)用戶在圖標(biāo)上使用其它的鼠標(biāo)動(dòng)作,例如雙擊。為了使程序響應(yīng)這些鼠標(biāo)動(dòng)作,TrayIcon提供了下列注冊(cè)listener的方法:· public void addActionListener(ActionListener listener):為TrayIcon添加一個(gè)動(dòng)作listener。當(dāng)用戶雙擊圖標(biāo)時(shí),這個(gè)listener的public void actionPerformed(ActionEvent e)方法將被調(diào)用。你也許想要在多個(gè)TrayIcon之間共享一個(gè)動(dòng)作listener,那么決定哪個(gè)圖標(biāo)響應(yīng)動(dòng)作事件并且調(diào)用listener就變得很重要了。你可以通過(guò)TrayIcon 的public void setActionCommand(String command)方法來(lái)為其分配一個(gè)唯一的指令。然后你就可以在listener中調(diào)用java.awt.event.ActionEvent的public String getActionCommand()方法來(lái)返回指令名稱以及識(shí)別TrayIcon。為方便起見,TrayIcon也指定了一個(gè)public String getActionCommand()方法。調(diào)用TrayIcon的public void removeActionListener(ActionListener listener)方法從TrayIcon上移除listener。你也可以通過(guò)調(diào)用public ActionListener [] getActionListeners()方法來(lái)獲取一個(gè)含有全部注冊(cè)的動(dòng)作listener的數(shù)組。· public void addMouseListener(MouseListener listener): 為TrayIcon添加一個(gè)鼠標(biāo)listener。當(dāng)鼠標(biāo)指針位于圖標(biāo)上方并且用戶按下、釋放、或者點(diǎn)擊鼠標(biāo)左鍵時(shí),這個(gè)listener的各種方法(除了public void mouseEntered(MouseEvent e)和public void mouseExited(MouseEvent e)不被支持)將會(huì)被調(diào)用。如果你調(diào)用java.awt.event.MouseEvent從父類繼承的public Component getComponent()方法,你將得到一個(gè)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)是相對(duì)于屏幕的——而不是TrayIcon。調(diào)用TrayIcon's public void removeMouseListener(MouseListener listener)方法可以從TrayIcon中移除listener。通過(guò)調(diào)用public MouseListener [] getMouseListeners()可以獲取含有所有注冊(cè)的鼠標(biāo)listener的一個(gè)數(shù)組。· public void addMouseMotionListener(MouseMotionListener listener): 為TrayIcon添加一個(gè)鼠標(biāo)運(yùn)動(dòng)listener。當(dāng)用戶在圖標(biāo)上移動(dòng)鼠標(biāo)指針時(shí),這個(gè)listener的public void mouseMoved(MouseEvent e)方法將被調(diào)用。(public void mouseDragged(MouseEvent e)方法不支持)再一次,getComponent()返回null,getSource()返回一個(gè)與事件相關(guān)聯(lián)的TrayIcon,getX()和getY()返回的坐標(biāo)是相對(duì)于屏幕的——而不是TrayIcon。調(diào)用TrayIcon的public void removeMouseMotionListener(MouseMotionListener listener)方法來(lái)從TrayIcon移除listener。你可以通過(guò)調(diào)用public MouseMotionListener [] getMouseMotionListeners()來(lái)得到一個(gè)含有全部注冊(cè)的鼠標(biāo)動(dòng)作listener的數(shù)組。表5展示了一個(gè)擁有自己的String工具提示和PopupMenu的程序SystemTrayDemo2。該程序也調(diào)用了之前介紹的listener注冊(cè)方法來(lái)注冊(cè)用于響應(yīng)動(dòng)作、鼠標(biāo)和鼠標(biāo)運(yùn)動(dòng)事件的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)建一個(gè)與程序的圖標(biāo)相關(guān)聯(lián)的彈出菜單。選擇菜單唯一的一個(gè)菜單項(xiàng)就會(huì)結(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)建一個(gè)圖標(biāo),當(dāng)鼠標(biāo)位于圖標(biāo)上方式,選擇顯示一個(gè)工具提示,以及為圖標(biāo)分配彈出式菜單。 TrayIcon ti = new TrayIcon (bi, 'System Tray Demo #2', popup); // 創(chuàng)建并且關(guān)聯(lián)一個(gè)listener到圖標(biāo)上。當(dāng)你采用了適當(dāng)?shù)膭?dòng)作,例如在Windows下雙擊鼠標(biāo),actionPerformed()方法將會(huì)被調(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)一個(gè)鼠標(biāo)listener來(lái)記錄于圖標(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)一個(gè)鼠標(biāo)運(yùn)動(dòng)listener來(lái)記錄于圖標(biāo)相關(guān)聯(lián)的鼠標(biāo)運(yùn)動(dòng)事件 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)。移動(dòng)鼠標(biāo)到圖標(biāo)上,除了在控制臺(tái)窗口顯示信息“Mouse moved之外,工具提示也將會(huì)出現(xiàn)。當(dāng)鼠標(biāo)指針位于圖標(biāo)上方時(shí),試一下左鍵單擊,各種按下、釋放、點(diǎn)擊消息將會(huì)在控制臺(tái)窗口出現(xiàn)。如果你雙擊圖標(biāo),動(dòng)作指令的名字將會(huì)在控制臺(tái)窗口出現(xiàn)。最后,右鍵單擊圖標(biāo),你將會(huì)看見一個(gè)帶有Exit選項(xiàng)的彈出菜單。表4演示了SystemTrayDemo2的圖標(biāo)的兩個(gè)視圖。在左側(cè)你能看見圖標(biāo)上的工具提示,在右側(cè)你可以看見圖標(biāo)的彈出菜單。 表4. 托盤圖標(biāo)有自己的工具提示和彈出菜單TrayIcon類提供了額外的一些方法——其中一些是通過(guò)構(gòu)造器調(diào)用的——你也許會(huì)感興趣。這些方法包括:· public void displayMessage(String caption, String text, TrayIcon.MessageType messageType): 在系統(tǒng)托盤上圖標(biāo)附近顯示一條彈出消息。這條消息持續(xù)的時(shí)間依賴于平臺(tái),之后便會(huì)消失。(我相信這個(gè)方法并不影響與TrayIcon相關(guān)聯(lián)的工具提示。)caption顯示在消息內(nèi)容text的上方,caption或text都可以為null,但是如果均為null,該方法將拋出NullPointerException。最后,messageType可以為下列消息類型之一:TrayIcon.MessageType.ERROR (錯(cuò)誤消息), TrayIcon.MessageType.INFO (通知消息), TrayIcon.MessageType.NONE (簡(jiǎn)單消息), or TrayIcon.MessageType.WARNING (警告消息)。當(dāng)消息出現(xiàn)時(shí),平臺(tái)可以使用messageType來(lái)決定什么動(dòng)作——顯示圖形還是發(fā)出聲音——需要被執(zhí)行。這個(gè)方法并不是所有的平臺(tái)都支持。例如,我在Windows ME平臺(tái)上就無(wú)法顯示消息。· public void setImage(Image image): 創(chuàng)建一個(gè)image作為TrayIcon的Image。這用于指示程序狀態(tài)的改變是非常方便的。前一個(gè)Image會(huì)丟棄而不調(diào)用Image的flush()方法——你必須明確的調(diào)用這個(gè)方法來(lái)轉(zhuǎn)儲(chǔ)所有被前一個(gè)Image對(duì)象使用的資源(包括為了屏幕繪制而緩存的像素?cái)?shù)據(jù))。如果image為null,該方法將拋出NullPointerException。調(diào)用public Image getImage()方法來(lái)返回當(dāng)前的Image。· public void setImageAutoSize(boolean autosize): 設(shè)置TrayIcon的自動(dòng)調(diào)整尺寸屬性。這個(gè)屬性決定了Image是否自動(dòng)調(diào)整尺寸來(lái)適應(yīng)分配給系統(tǒng)托盤圖標(biāo)的空間。如果你傳遞true給autosize,Image將按照需要自動(dòng)縮小或擴(kuò)大。否則,Image將被裁減以適應(yīng)分配的空間。調(diào)用public boolean isImageAutoSize()方法可以返回自動(dòng)調(diào)整大小屬性的值。· public void setPopupMenu(PopupMenu popup): 為TrayIcon設(shè)置彈出菜單。如果popup為null,沒(méi)有PopupMenu與相關(guān)聯(lián)TrayIcon。如果你試圖為不同的TrayIcon設(shè)置同樣的彈出菜單,該方法將拋出IllegalArgumentException。一些平臺(tái)也許不支持彈出菜單,當(dāng)用戶右鍵單擊圖標(biāo)時(shí),他們或者不顯示菜單,或者不顯示本地版本的菜單。調(diào)用public PopupMenu getPopupMenu()方法來(lái)返回當(dāng)前的PopupMenu。· public void setToolTip(String tooltip): 為TrayIcon設(shè)置工具提示。當(dāng)用戶把鼠標(biāo)移動(dòng)到系統(tǒng)托盤上的圖標(biāo)上方時(shí),工具提示會(huì)被顯示出來(lái)。傳遞null作為tooltip的值可以移除工具提示。工具提示在一些平臺(tái)上可能被簡(jiǎn)化了。調(diào)用public String getToolTip()方法來(lái)返回當(dāng)前的工具提示String。在文章的結(jié)尾,我希望可以避開一個(gè)潛在的易混淆點(diǎn)。 關(guān)于isSupported()方法的SystemTray文檔建議“將默認(rèn)動(dòng)作同時(shí)加入到動(dòng)作listener和彈出菜單中以便保證托盤圖標(biāo)的默認(rèn)動(dòng)作始終可用。這是什么意思呢?就是簡(jiǎn)單地向PopupMenu添加一個(gè)Default菜單項(xiàng),它擁有與你關(guān)聯(lián)到TrayIcon的動(dòng)作listener同樣的動(dòng)作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就要到來(lái)了,你一定已經(jīng)忍不住想要在今年晚些時(shí)候正式版問(wèn)世之前就體驗(yàn)一下這個(gè)最新的Java平臺(tái)。為了幫助你順利起步,本文展示了一些你也許可以在這個(gè)平臺(tái)上找到的小示例。本文關(guān)注了4個(gè)重要的新特性:控制臺(tái)輸入/輸出、分區(qū)空間方法、啟動(dòng)畫面API和系統(tǒng)托盤API。Jeff Friesen是一個(gè)自由軟件開發(fā)者和教育者,擅長(zhǎng)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新的啟動(dòng)畫面功能 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)文章:
主站蜘蛛池模板: 欧美久在线观看在线观看 | 欧美综合成人 | 97超级碰碰碰久久久观看 | 一级毛片一级毛片a毛片欧美 | 国产精品久久久久毛片真精品 | 国产成版人视频网站免费下 | 欧美午夜在线观看理论片 | 中文乱码字幕午夜无线观看 | 成人午夜视频免费观看 | 日韩一中文字幕 | 欧美特级一级毛片 | 中文字幕在线精品 | 免费观看国产精品 | 免费一级欧美片片线观看 | 亚洲人免费视频 | 日韩中文字幕网站 | 欧洲亚洲一区二区三区 | 日本综合欧美一区二区三区 | 手机在线观看毛片 | 港台三级在线观看 | 久久综合久久自在自线精品自 | 九九精品视频在线观看 | 亚洲国产天堂久久综合图区 | 欧美日韩在线永久免费播放 | 真正免费一级毛片在线播放 | 欧美三级三级三级爽爽爽 | 成人禁在线观看网站 | a级男女性高爱潮高清试 | 五月桃花网婷婷亚洲综合 | 亚洲精品综合欧美一区二区三区 | 伊人短视频 | 国产精品亚洲第五区在线 | 我不卡午夜 | 三级毛片大全 | 一色屋色费精品视频在线看 | 色屁屁一区二区三区视频国产 | 青青热久久国产久精品秒播 | 波多野结衣视频在线观看地址免费 | 国模偷拍在线观看免费视频 | 国产精品亚洲综合久久 | 草草视频在线观看 |