今天在使用Java作系統托盤圖標(TrayIcon),須要爲其增長一個右鍵彈出菜單(PopupMenu),在使用菜單項(MenuItem)時,遇到了一個很是痛苦的事情:中文亂碼~~~~。這個問題不常常碰到,可是一旦碰到就頭疼了,網上一搜,方法一大堆,但不多有方法能解決本身的問題,畢竟狀況不同。 java
今天搞了一天,終於搞出了一套方案。 apache
先說一下出問題的緣由: oracle
1. 本地系統區域語言字符集的問題,咱們的系統可能默認的字符集爲GB2312或GBK。 eclipse
2. Java源文件編碼字符的問題,若是使用eclipse能夠查看一下java source文件的編碼方式。 jvm
3. javac編譯時的字符問題,這一個問題很容易被忽略,運行一下javac能夠看到有一個encoding的參數能夠設置----這一個很重要。 maven
4. 要讀取文件的編碼和讀取時的字符集設置問題,若是咱們要用的字符串不是硬編碼在java源碼中,而是從資源文件中讀取時,就要注意這個問題了。 ide
要解決問題須要作到以下: 測試
1. 本地系統的語言字符能夠不用管,主要看後面三項。 ui
2. Java源文件的編碼,這一點很重要,最好使用utf8編碼。 編碼
咱們在編輯文件時默認使用的是本地系統的字符集(如GBK),因此對Java源文件要進行字符轉換或提早作好設置,對於UE使用 文件--->轉換--->...到UTF-8(Unicode 編輯),對於eclipse設置 Window-->Preferences-->General-->Content Types--> Java Source File。具體操做此處不詳述。
3. javac編譯時的參數設置,增長encoding參數,如:javac -encoding utf8 Test.java
對於這一點要特別注意,eclipse的編譯器是沒有使用該參數的,我也沒找到該如何設置該參數(注意這裏是編譯參數javac, 不是運行參數java或jvm, 不是run config中配置的),因此遇到這個問題的狀況下不能使用eclipse來編譯了,至少在能配置javac以前是這樣。
不能使用eclipse了怎麼辦呢,手工不是太可能,有幾種方案:
1. 手工編譯使用到MenuItem的類,目前只發現java.awt包會存在這個問題,swing包能很好的解決這種字符集變換的問題。
2. 使用其它編譯方式,如ant、Maven,它們都能配置javac。我如今就使用maven,只須要爲它的編譯器加入encoding配置,以下:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.6</source> <target>1.6</target> <encoding>utf8</encoding> </configuration> </plugin> ....
4. 要讀取的文件的字符編碼和讀取流編碼,對一個資源文件,咱們也要設置其編碼爲utf8(參照第2條,跟設置java源文件編碼是同樣的),同時在使用流讀取時也要設置流的讀取編碼(這個網上說java字符流的默認的是jvm的編碼,跟系統字符集一致)。
選說說個人場景吧,我要從一個文件中讀取字符串作爲MenuItem的Label值(打算作國際化,呵呵),因此就須要對這個資源文件作處理,讀取流代碼以下:
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(langFile), "utf8"));
這裏還要注意的是:在複製這個資源文件時,最好也設置一下編碼,如用ant複製時:
<echo message="copy conf"/> <copy file="D:\klaudisk-client\conf\settings.ini" tofile="D:\klaudisk-client\target\conf\settings.ini" overwrite="true" encoding="utf8"/>
好了,作到以上條件問題應該解決了。
在實際的過程當中咱們能夠經過如下步驟一步一步來達到以上條件,每步均可以測試。
1. 查看源文件的編碼
這一點很簡單,對於eclipse查看一下java source file編碼方式就好了,保險一點就是修改一下編碼方式,會發現原來的java文件(含中文的)亂碼了,再改回來,就行了。 編碼方式請設置爲utf8
2. 編譯編碼的測試
能夠先寫一個小例子,使用硬編碼的方式加入中文,如MenuItem m = new MenuItem("中文"),你用eclipse運行後能夠發現這個menu顯示的是亂碼(全是小方框)。而後你用命令行的方式編譯一下:javac -encoding utf8 Test.java。而後命令行運行,若是發現顯示正常了,則這及之前的測試經過了,若是仍是亂碼,則須要你再次確認第1步。
3. 在前2部都肯定成功的狀況下再考慮讀取資源文件的測試,這個參照前面說的就好了。
--OK,問題應該能解決了,這種方式還能夠應用到其它中文亂碼的問題上。
補充說明的是:awt不是不支持中文,是編碼轉換不夠智能。在swing中就解決了這些問題。
關於這個TrayIcon,我看oracle那邊已經提交了一個bug,意思是說要編寫一個對應的swing的JTrayIcon,從而使用JPopupMenu和JMenuItem。但這個bug不是因字符問題提交的。
對於MenuItem亂碼的問題,還可使用JPopupMenu和JMenuItem來替代,參照以下,但狀況不理想(彈出時必需要選擇一個菜單,不然不消失):
ImageIcon icon = new ImageIcon(UITest.class.getResource("16.gif")); TrayIcon tray = new TrayIcon(icon.getImage()); tray.setImageAutoSize(true); SystemTray.getSystemTray().add(tray); tray.addMouseListener(new MouseAdapter() { @Override public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) { final JPopupMenu pop = new JPopupMenu(); JMenuItem m1 = new JMenuItem("中文"); pop.add(m1); pop.add(new JMenuItem("主題")); pop.setLocation(e.getX(), e.getY()); pop.setInvoker(pop); pop.setVisible(true); } } });
另外,對於第4點,資源文件的問題,還可使用Properties.load()方法來加載.properties文件(該文件是被java bin下的navie2asc程序處理過的文件),這樣就不用管第4點問題了,但問題很顯然,不方便不直觀。
---EOF---