论坛首页 Java企业应用论坛

javaGUI字体讨论

浏览 5917 次
精华帖 (3) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-07-22  

我们知道java有5种逻辑字体,分别是 SerifSanserifMonospaceDialog 以及 DialogInput。当你在程序中比如

UIDefaults ui = UIManager.getLookAndFeelDefaults();

ui.put("TextArea.font", new FontUIResource("DialogInput", Font.BOLD, 14));

 

这样你对所有TextArea默认的字体设置成DialogInput了,但是DialogInput到底对应什么字体呢?这就取决于你的程序所在JRE的情况了,

$JRE_HOME/lib/fontconfig.properties.*文件定义了这5种逻辑字体分别映射到哪些具体的字体,不同的平台下情况可能不同,你当然也可以修改这个配置。

如果这个配置文件定义某个具体字体不存在,那么你的java程序字符显示就会出现”口口口口口口口口口口口口“。所以有时候一个程序某些平台上跑的好好的,

到另一个平台就会出现”口口口口口口口口口口口口“。

现在假设您直接设置某个具体字体,而不是逻辑字体,那么当然你就没有映射的问题,比如

UIDefaults ui = UIManager.getLookAndFeelDefaults();

ui.put("TextArea.font", new FontUIResource("Comic Sans MS", Font.BOLD, 20));

但是这样,如果你的目标平台上没有Comic Sans MS,也会出现”口口口口口口口口口口口口“,另外,一种字体也是有它对应支持的字符集的而不是什么字符都能支持的,比如"Comic Sans MS”这种字体不能支持中文,所以即使你的系统存在"Comic Sans MS"字体,但是在TextArea输入中文的时候也会出现”口口口口口口口口口口口“。

那么如果我打开NetBeans,画了个画面,不做什么设置,然后运行,一切OK,这时是什么字体呢?

获得 UIDefaults ui = UIManager.getLookAndFeelDefaults();然后遍历发现:

ToggleButton.font:javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=bold,size=12]
ComboBox.font:javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=bold,size=12]
ScrollPane.font:javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=plain,size=12]
Spinner.font:javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=bold,size=12]
RadioButtonMenuItem.font:javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=bold,size=12]
Slider.font:javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=bold,size=12]
EditorPane.font:javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=plain,size=12]
OptionPane.font:javax.swing.plaf.FontUIResource[family=Dialog,name=Dialog,style=plain,size=12]

。。。。。。。。。。。。。。。。。。。。。

都是Dialog字体,如果我在加一行代码:UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

我是在Windows环境下,所以应该得到Windows的LookAndFeel。

这时再遍历发现:

ToggleButton.font:javax.swing.plaf.FontUIResource[family=SimSun,name=宋体,style=plain,size=12]
ComboBox.font:javax.swing.plaf.FontUIResource[family=SimSun,name=宋体,style=plain,size=12]
ScrollPane.font:javax.swing.plaf.FontUIResource[family=SimSun,name=宋体,style=plain,size=12]
Spinner.font:javax.swing.plaf.FontUIResource[family=SimSun,name=宋体,style=plain,size=12]
RadioButtonMenuItem.font:javax.swing.plaf.FontUIResource[family=SimSun,name=宋体,style=plain,size=12]
Slider.font:javax.swing.plaf.FontUIResource[family=SimSun,name=宋体,style=plain,size=12]
EditorPane.font:javax.swing.plaf.FontUIResource[family=SimSun,name=宋体,style=plain,size=12]
OptionPane.font:javax.swing.plaf.FontUIResource[family=SimSun,name=宋体,style=plain,size=12]

。。。。。。。。。。。。。。。。。。。。。

是宋体,是一个具体字体而不是逻辑字体,说明Swing几个内置的实现几个主要系统的LookAndFeel,会设置对应系统常用字体,比如因为我是

Windows系统所以配了宋体,想必只要是中文Windows系统不可能没有宋体吧。

现在很多人写的Swing程序,一般也不会特地去设定自己的字体,而是没设,然后一般又会加载当前系统的LookAndFeel,所以会写上一句

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

但是听说有些Swing程序在Windows好的到了其他环境出现”口口口口口口口口口口口口“,如果是以上的写法(没有特地设置过字体),那么按理说

会设置对应系统常用字体,如果因为目标系统没有这个字体,而出现”口口口口口口口口口口口口“,对于Swing对应LookAndFeel的实现来说一定找的是

常用字体,为何目标系统会缺乏呢?是目标系统的错还是java的错?java对于常用字体的判定错误?我就不清楚了。

 

所以理论上来说如果我不设置字体,并且写UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());那么对应LookAndFeel会设定一个默认对应系统的常用字体,如果实现的好,那么确实是运行各个环境都没有问题。但是现实是没有那么完美。当然还有很多第三方LookAndFeel,他们对于UIDefaults的设置是什么,可以通过 UIManager.getLookAndFeelDefaults();获得。

 

 

这上面说的是Swing,但是AWT组件默认的字体是怎样决定呢?这个本来也真没想管它,因为本更不会去用AWT组件,但是当我要做系统托盘图标的时候发现问题来了,因为SystemTray st = SystemTray.getSystemTray();然后st可以加入TrayIcon,而TrayIcon只能放PopupMenu,注意是PopupMenu而不是JPopupMenu,所以是AWT组件,然后构造MenuItem放入PopupMenu,如果传入MenuItem的是中文字符,结果运行点击托盘图标时菜单出现”口口口口口口“了。我调用item.getFont()查看字体,但是MenuItem返回的是null,这下我不解了,查查资料也没有结果,所以关于AWT组件这个问题我也不清楚,有人是否能解释一下呢?其实关于字体,这里说的还不够,真希望有更全面的解释一下这个主题。

 

 

 

 

 

 

   发表时间:2009-07-23  
关于MenuItem中文字符”口口口口口口“问题来源我找到了,我的源代码文件是UTF-8在Eclipse里面改为GBK后,再运行能正常显示中文,我觉得这很奇怪,为什么要判定我的源代码文件编码方案呢?
我再改回UTF-8,然后打包出去,然后运行打包后的jar,发现没有问题,可以显示,但是如果在Eclipse里面运行就会有”口口口口口口“,这下我晕了,这是为什么啊?难道Eclipse依据我的源代码编码方案向VM传了什么参数,然后AWT依据这个参数的设置来处理,然后出现了问题”口口口口口口“。毕竟打包出去的jar没有”口口口口口口“。
Swing的组件是没有这个问题的,AWT的机制到底是怎样的呢?
望诸位解释解释啊。
1 请登录后投票
   发表时间:2009-07-24  
又有了一些进展,原来对源代码文件的编码方案设定会影响java的“file.encoding”属性,自然也就影响到比如String的getbytes()方法的结果,getbytes()方法的文档里面解释似乎是依据本地平台的编码方案进行Byte化,我一开始理解为就是按本地操作系统的字符集来byte化,但是实际上不一定,因为VM启动时有个参数可以设定的,就是-Dfile.encoding=XXX ,而IDE开发环境似乎会根据你的源代码文件的编码方案来对VM设定这个参数,但是如果你强行设定了这个参数,那么就以你设定的为准。
所以我源代码编码方案还是“UTF-8”,但是我VM启动参数里面加了这一行-Dfile.encoding=GBK,那么运行结果最后也是正常的。可见AWT机制相当粗糙,它可能会对字符串直接getbytes(),然后会将这堆bytes再调用本地操作系统API,比如我在Windows上的话,本地操作系统的当前字符集是GBK,而这堆Bytes是以UTF-8编码的,windows的API如果以GBK解它的话,自然也就完蛋了。
1 请登录后投票
   发表时间:2009-07-24  
其实这也引出了另外一个问题,就是java到底如何获得本地操作系统的当前字符集而不仅仅是java VM的当前字符集?因为java VM的当前字符集完全可以在VM启动时设定的,它很可能和本地操作系统不一致。
1 请登录后投票
   发表时间:2010-07-20  
系统托盘我也遇到过,一直没有解决。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics