今天在使用Java做系统托盘图标(TrayIcon),需要为其增加一个右键弹出菜单(PopupMenu),在使用菜单项(MenuItem)时,遇到了一个非常痛苦的事情:中文乱码~~~~。这个问题不经常碰到,但是一旦碰到就头疼了,网上一搜,方法一大堆,但很少有方法能解决自己的问题,毕竟情况不一样。
今天搞了一天,终于搞出了一套方案。
先说一下出问题的原因:
1. 本地系统区域语言字符集的问题,我们的系统可能默认的字符集为GB2312或GBK。
2. Java源文件编码字符的问题,如果使用eclipse可以查看一下java source文件的编码方式。
3. javac编译时的字符问题,这一个问题很容易被忽略,运行一下javac可以看到有一个encoding的参数可以设置----这一个很重要。
4. 要读取文件的编码和读取时的字符集设置问题,如果我们要用的字符串不是硬编码在java源码中,而是从资源文件中读取时,就要注意这个问题了。
要解决问题需要做到如下:
1. 本地系统的语言字符可以不用管,主要看后面三项。
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---
分享到:
相关推荐
android 开发MenuItem显示中文乱码.docx
在本篇JavaFX+Jfoenix学习笔记中,我们将探讨如何在JavaFX应用程序中实现系统托盘功能,以及如何解决可能出现的中文乱码问题。系统托盘是现代桌面应用中常见的一种特性,允许用户在关闭主窗口后,仍然可以通过托盘...
通过设置`Header`属性,我们可以指定MenuItem显示的文本。例如: ```xml <MenuItem Header="文件"> <MenuItem Header="新建"/> <MenuItem Header="打开"/> </MenuItem> ``` 在这个例子中,“文件”是顶级...
`.sln`和`.suo`文件是Visual Studio解决方案和用户选项的存储,它们不直接涉及代码逻辑,但对开发环境有影响。 在实际项目中,我们可能还需要处理更多细节,如字体、颜色、动画效果等。`1.ico`和`2.ico`可能是应用...
- `WpfMenuItem.sln`是Visual Studio的解决方案文件,包含了项目的所有相关信息,包括项目文件、引用和配置设置。 - `WpfMenuItem.csproj`是项目的实际构建文件,定义了编译和构建过程。 6. **项目配置**: - `...
WPF中MenuItem原生样式
### 常见的Java中文问题及解决方法 在Java编程过程中,中文显示与处理问题时常困扰开发者。本文将深入探讨几种常见的Java中文问题及其解决方案,并着重分析如何通过设置字体来改善用户界面中的中文显示效果。 ####...
在这个项目中,我们关注的是如何在STM32上利用OLED显示器来实现汉字菜单的显示功能。OLED(有机发光二极管)显示器因其高对比度、低功耗和小巧的体积而被广泛应用。 首先,我们要理解STM32与OLED显示器的交互原理。...
C#WPF 右键菜单 显示 事件触发 测试通过 <!-- 设置右键菜单 --> <MenuItem Header="编辑"> <!-- 调用系统命令 --> <MenuItem Command="Copy"></MenuItem> <MenuItem Command="Cut"></MenuItem> <MenuItem...
下面将详细介绍`MenuItem`的使用方法及其在自定义编辑器窗口中的应用。 首先,`MenuItem` 是Unity3D中`UnityEditor`命名空间下的一个属性标记,用于在Unity编辑器的主菜单栏中添加新的菜单项。它的基本语法是: ``...
在Android应用开发中,`Fragment`是用于构建可重用屏幕部分的重要组件,而`MenuItem`则是在Android的`OptionsMenu`或`Action Bar`中显示的用户操作选项。`Fragment Handle MenuItem`涉及到如何在`Fragment`中处理...
例如,`TreeView`用于显示整个网站的层级结构,`MenuItem`处理用户的点击事件,引导用户到相应页面,而`SiteMapPath`则提供当前页面在网站结构中的位置信息,提升用户体验。 在实际应用中,开发者通常会利用`...
在Android应用开发中,MenuItem是菜单项对象,通常用于在Action Bar或Overflow Menu中显示用户可操作的选项。为了提供更丰富的交互体验,有时我们需要自定义MenuItem的长按事件,而不是仅依赖系统默认的行为。本篇...
默认的MenuItem样式比较普通,这次自定义MenuItem的样式也只是对MenuItem的颜色风格进行变化。需要其他功能的变化,大家可以根据样式代码进行扩展。 MenuItem的样式代码: <!--MenuItem--> <Style Target...
快速创建menuItem控件,使用简单,可扩展,默认提供了很多种类型,使用时只需要把需要的枚举类型加到初始化数组即可 初始化 lazy var menuItem:CLMenuView = { let menuItem = CLMenuView(itemTypes: [.copy,....
因此,这种解决方案应当作为最后的手段,并且需要对可能的风险有所认识。 总之,当在Android 4.0中遇到菜单图标无效的问题时,可以尝试使用反射技术来解决。不过,为了保证应用的稳定性和兼容性,更推荐遵循官方...
在实际项目中,我们还可以结合`onPrepareOptionsMenu(Menu menu)`方法来更新菜单的状态,比如根据用户权限或当前数据状态来显示或隐藏某些菜单项。 综上所述,理解和掌握`Menu`, `SubMenu`, `MenuItem`的使用是...