如何在 java swing 运行时更改语言
Posted
技术标签:
【中文标题】如何在 java swing 运行时更改语言【英文标题】:How to change language at runtime in java swing 【发布时间】:2012-10-20 13:50:46 【问题描述】:我尝试在我的 swing 应用程序中在运行时更改语言环境。 但我不知道它应该如何运作,或者没有总体规划?
我只能想到两个选择: 1.重启应用,不是最好的用户体验。 2. 创建一个可以注册/注销组件的本地化管理器,在更改时它只是迭代所有组件并更改文本。
1和2都觉得别扭。
其他信息: 目前,方向不是目标。 应用程序被混淆了。
例子:
LocRes_en.properties:
text1 = 英文文本LocRes_ja.properties
text1 = 日文文本ChangeLocale.java:
导入 java.awt.EventQueue; 导入 java.awt.FlowLayout; 导入 java.awt.event.ActionEvent; 导入 java.awt.event.ActionListener; 导入 java.util.Locale; 导入 java.util.ResourceBundle; 导入 javax.swing.JButton; 导入 javax.swing.JFrame; 导入 javax.swing.JLabel; 公共类 ChangeLocale 私有 JFrame 框架; 公共静态无效主要(字符串[]参数) EventQueue.invokeLater(new Runnable() 公共无效运行() 尝试 ChangeLocale 窗口 = new ChangeLocale(); window.frame.setVisible(true); 捕捉(异常 e) e.printStackTrace(); ); 公共更改区域设置() 初始化(); 私人无效初始化() 框架 = 新的 JFrame(); frame.setBounds(100, 100, 450, 300); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); FlowLayout flowLayout = new FlowLayout(FlowLayout.CENTER, 5, 5); frame.getContentPane().setLayout(flowLayout); JButton btnChangeLoc = new JButton("更改语言环境"); frame.getContentPane().add(btnChangeLoc); final JLabel lblLabel1 = new JLabel("新标签"); frame.getContentPane().add(lblLabel1); Locale.setDefault(new Locale("en")); ResourceBundle r = ResourceBundle.getBundle("LocRes"); lblLabel1.setText(r.getString("text1")); btnChangeLoc.addActionListener(new ActionListener() 公共无效actionPerformed(ActionEvent e) Locale.setDefault(new Locale("ja")); ResourceBundle r = ResourceBundle.getBundle("LocRes"); // 手动遍历所有组件 :( lblLabel1.setText(r.getString("text1")); // );【问题讨论】:
never needed that, but there are must be some examples about loading properties to the HashMap or List 【参考方案1】:定义一个GUI
和一个支持语言的组合框。添加ItemListener
,以便在更改组合框时更新文本。
LanguageGUIClient.java:
import javax.swing.*;
public class LanguageGUIClient
public static void main(String[] arguments) throws Exception
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(() ->
LanguageGUI languageGUI = new LanguageGUI();
languageGUI.setVisible(true);
);
LanguageGUI.java:
import javax.swing.*;
import java.util.Locale;
import java.util.ResourceBundle;
public class LanguageGUI extends JFrame
public static ResourceBundle resourceBundle;
private JPanel rootPanel;
private JComboBox<Locale> languageComboBox;
private JLabel languageLabel;
public LanguageGUI()
configureFrameProperties();
private void configureFrameProperties()
add(rootPanel);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
languageComboBox.addItem(Locale.US);
languageComboBox.addItem(Locale.GERMANY);
languageComboBox.addItem(Locale.FRANCE);
setTexts();
languageComboBox.addItemListener(itemEvent -> setTexts());
setSize(300, 100);
private void setTexts()
Locale locale = languageComboBox.getItemAt(languageComboBox.getSelectedIndex());
resourceBundle = ResourceBundle.getBundle("Bundle", locale);
setTitle(resourceBundle.getString("application.title"));
languageLabel.setText(resourceBundle.getString("language") + ":");
languageComboBox.setToolTipText(resourceBundle.getString("language.tooltip"));
请注意,我使用的是IntelliJ's form designer
,所以.form
文件内容也是必需的。
LanguageGUI.form:
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="LanguageGUI">
<grid id="27dc6" binding="rootPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" />
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="eb651" class="javax.swing.JComboBox" binding="languageComboBox">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<toolTipText value=""/>
</properties>
</component>
<vspacer id="977c1">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="e59f" class="javax.swing.JLabel" binding="languageLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value=""/>
</properties>
</component>
</children>
</grid>
</form>
此外,您需要在资源目录中创建相应的资源包文件:
结果是一个GUI
,带有一个允许您立即更改语言的组合框:
【讨论】:
别忘了将“resources”文件夹也添加到构建路径中(Eclipse:右键项目-属性-Java Builder路径-源代码-添加文件夹),否则会有成为java.util.MissingResourceException: Can't find bundle for base name Bundle, locale en_US
例外。【参考方案2】:
我已经使用 ResourceBundles 和 EventBus 实现了这一点。
当区域设置改变时,EventBus 会触发一个localeChangedEvent
。所有具有本地化字符串的JFrame
窗口都必须订阅此事件。他们还必须实现一个changeLocale()
方法,该方法在收到事件时执行。
在此方法中,所有字符串都将更新为当前语言环境。
public void changeLocale(ResourceBundle rb)
lblLabel1.setText(rb.getString("text1"));
lblLabel2.setText(rb.getString("text2"));
...
【讨论】:
【参考方案3】:你可以试试LocaleChangeListener接口——
Changing locale at runtime in Swing
【讨论】:
【参考方案4】:我曾经做过类似的事情。虽然我的任务更简单:这是一个系统托盘应用程序,所以我只需要更改菜单项文本。
但在你的情况下,我认为这是可行的。首先,避免在 GUI 层中使用硬编码字符串。创建更改语言环境的类,然后迭代所有可见框架,并深入到所有面板和组件并更改写在它们上的文本。我能想到的唯一问题是在画布上绘制的文本。
【讨论】:
以上是关于如何在 java swing 运行时更改语言的主要内容,如果未能解决你的问题,请参考以下文章
Java / Swing:JScrollPane中的JTextArea,如何防止自动滚动?
Java Swing 在等待方法时在 actionPerformed 函数中更改 UI 两次