Swing国际化 - 如何在运行时更新语言
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swing国际化 - 如何在运行时更新语言相关的知识,希望对你有一定的参考价值。
我跟着Googles howto for its Window Builder Pro extension国际化我的应用程序。将在标签中显示的字符串现在存储在由“Externalize Strings”向导创建的属性文件中(我使用了经典的eclipse消息文件)。
在我的qazxsw poi方法中,我的所有标签都被初始化,它们的文本设置如下:
initialize
我在我的类JLabel lblLanguage = new JLabel(Messages.getString("App.lblLanguage.text")); //$NON-NLS-1$
中创建了一个包含GUI的枚举类型:
App
该语言将使用组合框设置,该组合框使用枚举类型Lang来显示可用的语言:
private enum Lang { German(Locale.GERMAN), English(Locale.ENGLISH);
private Locale loc;
Lang (Locale l) {
loc = l;
}
Locale getLocale() {
return loc;
}
}
我发现了许多其他的howtos和教程,涵盖了swing应用程序的国际化,但它们都没有涵盖如何更新所有标签(以及其中可能包含文本的其他控件)。这里有 JComboBox cboLanguage = new JComboBox();
cboLanguage.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource();
Lang l = (Lang)cb.getSelectedItem();
// TODO: update language
}
});
cboLanguage.setModel(new DefaultComboBoxModel(Lang.values()));
,如果链接没有死,可能会有所帮助。
因为我对java中的GUI编程有点陌生,我现在不知道该怎么做,这是我的问题:
- 如果设置了新语言,在运行时更改所有控件的语言的最佳方法是什么?
- 是否可以(推荐)将所有控件声明为我的App类的私有成员,以使方法更新其文本属性( - > this answer方法会这样做)
我通过扩展JLabel并覆盖getText来返回对语言选择的评估来解决这个问题。
您还需要一些发布/订阅机制来“告诉”您的标签语言已更改。
在这里我使用updateLanguage
Guava event bus
当用户更改语言时,您将触发事件:
import com.google.common.eventbus.EventBus;
public class EventBusHolder {
private static EventBus bus = new EventBus();
public static EventBus get() {
return bus;
}
}
要使用的标签组件:
JComboBox cboLanguage = new JComboBox();
cboLanguage.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox cb = (JComboBox)e.getSource();
Lang l = (Lang)cb.getSelectedItem();
// this is the event fire
ChangeEvent event = getChangeEvent(l);
EventBusHolder.get().post(event);
}
});
当您实例化标签时,您必须传递密钥进行翻译:
public class MyLabel extends JLabel {
private static final long serialVersionUID = 1L;
public MyLabel (String key) {
super(key);
// register this in event bus
EventBusHolder.get().register(this);
}
@Override
public String getText() {
return Messages.getString(super.getText());
}
@Subscribe
public void recordCustomerChange(ChangeEvent e) {
revalidate();
}
}
有关JLabel lbl = new JLabel("App.lblLanguage.text");
的更多用法示例
当我这样做时,我找不到内置的方式。
所以我创建了自己的guava event bus界面。实现了所有UI屏幕/面板,并在我的中央UI控制器类上将自己注册为侦听器。然后每当语言改变时,就会向每个人发出LocaleChangeListener
电话。我保持组件初始化是分开的 - 不需要再次完成所有这些。
他们只有这样的代码:
public void localeChanged(Lang lang) { nameLabel.setText(lang.getText("label.name")); submitButton.setText(lang.getText("button.submit")); etc... // I think on some screens I needed this to fix some quirky JTable/JTabbedPane layout issues: this.revalidate(); }
由于用户不会经常更改语言,因此重启几乎不可接受。这样做的好处是,旧语言的布局工件不会破坏文本。
这需要应用程序的可保存状态。
JLabel localeChanged(lang)
会立即评估本地化文本,并可能布局到该文本的宽度。所以这不适合动态语言变化。
另一种方法是依靠名称属性或反射来填充所有文本值。或代码:
new JLabel(Messages.getString("App.lblLanguage.text"));
有些Nls.setText在集合中对lblLanguage进行弱引用。
核心Swing中没有任何东西可以缓解疼痛。如果您使用某种支持资源注入的应用程序框架,您可能会感到高兴,如f.i. (更好)SwingApplicationFramework。
假设所有文本都像往常一样在属性文件中声明,类似下面的代码片段就可以了:
JLabel lblLanguage = new JLabel();
Nls.setText(lblLanguage, "App.lblLanguage");
刚发现一些故障:
- 不更新框架标题(可能是因为那不是bean属性)
- 不更新操作文本(可能需要强制某些上下文操作更新,不确定)
以上是关于Swing国际化 - 如何在运行时更新语言的主要内容,如果未能解决你的问题,请参考以下文章
linux打开终端如何启动scala,如何在终端下运行Scala代码片段?