MenuItem 顯示中文亂碼問題解決方案 | 您所在的位置:網(wǎng)站首頁 › trayicon › MenuItem 顯示中文亂碼問題解決方案 |
今天在使用Java做系統(tǒng)托盤圖標(biāo)(TrayIcon),需要為其增加一個右鍵彈出菜單(PopupMenu),在使用菜單項(MenuItem)時,遇到了一個非常痛苦的事情:中文亂碼~~~~。這個問題不經(jīng)常碰到,但是一旦碰到就頭疼了,網(wǎng)上一搜,方法一大堆,但很少有方法能解決自己的問題,畢竟情況不一樣。 今天搞了一天,終于搞出了一套方案。 先說一下出問題的原因: 1. 本地系統(tǒng)區(qū)域語言字符集的問題,我們的系統(tǒng)可能默認(rèn)的字符集為GB2312或GBK。 2. Java源文件編碼字符的問題,如果使用eclipse可以查看一下java source文件的編碼方式。 3. javac編譯時的字符問題,這一個問題很容易被忽略,運(yùn)行一下javac可以看到有一個encoding的參數(shù)可以設(shè)置----這一個很重要。 4. 要讀取文件的編碼和讀取時的字符集設(shè)置問題,如果我們要用的字符串不是硬編碼在java源碼中,而是從資源文件中讀取時,就要注意這個問題了。 要解決問題需要做到如下: 1. 本地系統(tǒng)的語言字符可以不用管,主要看后面三項。 2. Java源文件的編碼,這一點(diǎn)很重要,最好使用utf8編碼。 我們在編輯文件時默認(rèn)使用的是本地系統(tǒng)的字符集(如GBK),所以對Java源文件要進(jìn)行字符轉(zhuǎn)換或提前做好設(shè)置,對于UE使用 文件--->轉(zhuǎn)換--->...到UTF-8(Unicode 編輯),對于eclipse設(shè)置? Window-->Preferences-->General-->Content Types--> Java Source File。具體作此處不詳述。 3. javac編譯時的參數(shù)設(shè)置,增加encoding參數(shù),如:javac -encoding utf8 Test.java 對于這一點(diǎn)要特別注意,eclipse的編譯器是沒有使用該參數(shù)的,我也沒找到該如何設(shè)置該參數(shù)(注意這里是編譯參數(shù)javac, 不是運(yùn)行參數(shù)java或jvm, 不是run config中配置的),所以遇到這個問題的情況下不能使用eclipse來編譯了,至少在能配置javac之前是這樣。 不能使用eclipse了怎么辦呢,手工不是太可能,有幾種方案: 1. 手工編譯使用到MenuItem的類,目前只發(fā)現(xiàn)java.awt包會存在這個問題,swing包能很好的解決這種字符集變換的問題。 2. 使用其它編譯方式,如ant、Maven,它們都能配置javac。我現(xiàn)在就使用maven,只需要為它的編譯器加入encoding配置,如下: Java代碼 ? ??? ? ??????? ? ??????????? org.apache.maven.plugins? ??????????? maven-compiler-plugin? ??????????? 2.3.2? ??????????? ? ??????????????? 1.6? ??????????????? 1.6? ??????????????? utf8? ??????????? ? ??????? ? ????????????????????? ....? org.apache.maven.plugins maven-compiler-plugin 2.3.2 1.6 1.6 utf8 ....4. 要讀取的文件的字符編碼和讀取流編碼,對一個資源文件,我們也要設(shè)置其編碼為utf8(參照第2條,跟設(shè)置java源文件編碼是一樣的),同時在使用流讀取時也要設(shè)置流的讀取編碼(這個網(wǎng)上說java字符流的默認(rèn)的是jvm的編碼,跟系統(tǒng)字符集一致)。 選說說我的場景吧,我要從一個文件中讀取字符串做為MenuItem的Label值(打算做國際化,呵呵),所以就需要對這個資源文件做處理,讀取流代碼如下: Java代碼 BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(langFile), "utf8"));? BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(langFile), "utf8"));這里還要注意的是:在復(fù)制這個資源文件時,最好也設(shè)置一下編碼,如用ant復(fù)制時: Xml代碼 ? ?好了,做到以上條件問題應(yīng)該解決了。 在實際的過程中我們可以通過以下步驟一步一步來達(dá)到以上條件,每步都可以測試。 1. 查看源文件的編碼 這一點(diǎn)很簡單,對于eclipse查看一下java source file編碼方式就行了,保險一點(diǎn)就是修改一下編碼方式,會發(fā)現(xiàn)原來的java文件(含中文的)亂碼了,再改回來,就好了。 編碼方式請設(shè)置為utf8 2. 編譯編碼的測試 可以先寫一個小例子,使用硬編碼的方式加入中文,如MenuItem m = new MenuItem("中文"),你用eclipse運(yùn)行后可以發(fā)現(xiàn)這個menu顯示的是亂碼(全是小方框)。然后你用命令行的方式編譯一下:javac -encoding utf8 Test.java。然后命令行運(yùn)行,如果發(fā)現(xiàn)顯示正常了,則這及以前的測試通過了,如果還是亂碼,則需要你再次確認(rèn)第1步。 3. 在前2部都確定成功的情況下再考慮讀取資源文件的測試,這個參照前面說的就行了。 --OK,問題應(yīng)該能解決了,這種方式還可以應(yīng)用到其它中文亂碼的問題上。 補(bǔ)充說明的是:awt不是不支持中文,是編碼轉(zhuǎn)換不夠智能。在swing中就解決了這些問題。 關(guān)于這個TrayIcon,我看oracle那邊已經(jīng)提交了一個bug,意思是說要編寫一個對應(yīng)的swing的JTrayIcon,從而使用JPopupMenu和JMenuItem。但這個bug不是因字符問題提交的。 對于MenuItem亂碼的問題,還可以使用JPopupMenu和JMenuItem來替代,參照如下,但情況不理想(彈出時必須要選擇一個菜單,否則不消失): Java代碼 ????????????? 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);? ??????? }? ??? }? });? 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點(diǎn),資源文件的問題,還可以使用Properties.load()方法來加載.properties文件(該文件是被java bin下的navie2asc程序處理過的文件),這樣就不用管第4點(diǎn)問題了,但問題很顯然,不方便不直觀。 ---EOF--- |
今日新聞 |
推薦新聞 |
專題文章 |
CopyRight 2018-2019 實驗室設(shè)備網(wǎng) 版權(quán)所有 |