国际化Java Swing桌面应用程序的最佳实践是什么?
我确信有很多方法,但建议的方法是什么,对代码的影响最小?
显而易见的是,您创建了属性文件,但是如何在渲染中交换值? 在J2EE中,您只需重新渲染整个页面,这样就很容易了。 但是在Swing应用程序中,您只是在paintComponent(Graphics g)方法中添加.getProperty()的代码吗?
如果是这样的话,它看起来不是很重,因为现在你不得不在你不需要之前的所有地方覆盖这个方法……
附加:如何设置通知系统以重新渲染所有当前可见的组件而不强制某种注册模式?
我想如果我覆盖paintComponent(Graphics g),我所要做的就是触发一个事件已经改变了,并且将调用paintComponent(Graphics g)方法……
据我所知,一些应用程序使用布局/组件构建器 (由Karsten Lentzsch建议,以及JGoodies API的一部分)。 这些构建器包括用于本地化组件的代码(在引擎盖下使用ResourceBundle
)。
其他人(包括我)更喜欢资源注入 ; 这通常是侵入性最小的方法。 这是Swing应用程序框架 (JSR-296)和其他GUI框架(如Guts-GUI)选择的方式 。
您可能还想看看这个与您的问题非常相似的问题 。
关于“动态” Locale
变化( Locale
变更通知),我认为在使用资源注入时更容易实现(我已经在Guts-GUI中实现了这一点,Swing应用程序框架可能也有,但我不确定它)。
Java无法监听Locale
更改,因此您必须创建自己的“区域设置服务”(应将任何区域设置更改请求发送到该服务)。 在此服务中,您必须枚举所有可见窗口(这可以使用Window.getWindows()
,之前不需要注册可见组件)然后再次注入资源。
如果您想要一个示例,请查看Guts-GUI源代码中的resource
包:
- ResourceInjector显示资源注入和更改
Locale
方法,它发送一个通知事件(使用事件总线 ,但简单的侦听器也可以)关于此更改 - WindowController侦听Locale更改事件
更新所有可见窗口的有趣代码将在以下复制:
for (Window window: Window.getWindows()) { if (window.isVisible()) { injectResources(window); window.repaint(); if (window instanceof RootPaneContainer) { ((RootPaneContainer) window).getRootPane().revalidate(); } } }
支持动态语言更改是一个棘手的问题。 最简单的解决方案是以可以重新创建任何可见面板的方式组织UI。 这样可以避免注册或更新组件的需要,当语言发生变化时,您只需重新创建视图。
显然,您丢失了可能存在问题的所有可见组件的状态 – 但在刷新页面时,Web应用程序中的状态通常是相同的。
Java 6 SE允许您即时重新加载资源包。 只需调用ResourceBundle
类的clearCache()
静态函数即可。 然后再次调用getBundle ()
。
请参阅缓存控件下的这篇文章
我想出的唯一解决方案是创建一个需要重新渲染的所有组件的大量注册表。 然后,如果调用切换Locale,您只需调用注册表,它将遍历所有已注册的组件并调整其值。 因此,例如对于所有已注册的JLabel,它将执行某些操作
for(JLabel specificJLabel : REGISTRY.registeredJLabels) { String localeKey = specificJLabel.getActionCommand(); specificJLabel.setText(ResourceBundle.getString(localeKey)); }
Locale键存储在组件ActionCommand中的位置。 然后,无论当前呈现什么屏幕,主父面板都负责重新呈现它。 此外,注册表不必管理区域设置密钥,这些密钥与注册表完全分离。 每个组件都负责管理它自己的ResourceBundle的Locale Keys。
你需要的是一个ResourceBundle,它允许你拥有基于Locale的属性文件,你只需要像属性文件那样访问它。
以下是如何操作的示例