使按钮操作在 Java 中的多个 类 中起作用

Making a button action work across multiple classes in Java

我正在 Java 中制作一个计算器,但我似乎无法获得按钮的 actionListener 来改变其他 4 个 类 中的内容。我想要的是按钮将程序中的文本从英语更改为西班牙语。我的程序由 5 个 类 组成,我希望每个 JLabel、按钮和菜单中的语言都发生变化。

这是我的按钮监听器代码:

btnLanguage = new JButton("Language");
    btnLanguage.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            btnAddition.setText("Añadir");
            btnDivide.setText("Dividir");
            btnMultiply.setText("Se multiplican");
            btnSubtract.setText("Reste");
            btnLanguage.setText("Idioma");
        }
    });

我也想知道Windows是否会自动将程序中的文本更改为系统语言。

提前致谢!

不幸的是,Swing 没有很好的 l10n 支持 build in。你需要自己处理标签重命名等。

通常swing支持的是Java资源包的概念,就是选择UI之前的所有文字的资源是build。

在您的代码中,您将不再收到短信,但您将从您的包中获取字符串。

这里有 4 个包文件,以至少您想要的语言的中缀命名。

# Bundle file lang.properties
button.addition.text=Add

# Bundle file lang_de.properties
button.addition.text=Addieren

# Bundle file lang_en.properties
button.addition.text=Add

# Bundle file lang_fr.properties
button.addition.text=Addition

在您的代码中,您在 build ui 之前加载资源包(例如在名为 App 的 class 中):

public static ResourceBundle R;

public static void main(String[] args) {
   Locale l = new Locale(args[0], args[1]); // should have a check here :-)
   R = ResourceBundle.getBundle("l10n/lang.properties", l); 
}

当您初始化 UI 时,您将调用 use:

JButton btn = new JButton();
btn.setText(App.R.getString("button.addition.text"));

这允许在运行时不切换。不过,您可以使用 Java8 lambda 并为 L10nService 上的翻译文本注册所有带有 setter 的标签载体。

public class L10nService {
    ResourceBundle R = .... // initialize or change at runtime

    private List<LabelSetter> setters = new ArrayList<LabelSetter>();

    public void addSetter(LabelSetter setter) {
        setters.add(setter);
    }

    public void changeLanguage(Locale l) {
        R = ResourceBundle.getBundle("l10n/lang", l);
        for(LabelSetter s : setters) {
             s.set(R);
        }
    }
}

在您的 UI 中,您将创建 uild UI,并为每个要翻译的元素注册 LabelSetter:

void buildUi(L10nService fac, Locale l) {
    JButton btn = new JButton();
    LabelSetter s = R -> btn.setText(R.getText("button.addition.text"));
    fac.addSetter(s);

    // ... continue adding ui elements

   // when you are ready to build: 
   fac.changeLanguage(l);
}

注意:这有缺点。虽然您可以在运行时非常轻松地切换语言,但即使您销毁了它们曾经居住的容器,您也会将 UI 元素保留在内存中。这是因为它们在闭包 LabelSetter 中,你已经注册了。只要这个闭包存在,你的 UI 对象就不会消失。因此,在销毁 UI 元素时,您需要确保将它们也从 L10nService 中移除。此外,如果所有标签都发生变化,swing 可能需要ui重新绘制和重新布局。 这里的好处是,您实际上可以让 swing 库通过 ResourceBundles 了解 l10n 更改,并且语言切换会自行传播。

或者,您可以实现一个 L10nTextSource,它发出 LocaleChangedEvents。您的 UI classes 会监听这些事件并自行重写。这里的缺点是,您需要扩展每个要添加功能的 UI 元素,或者至少要将功能添加到您的组件。