JavaFX:在运行时更改应用程序语言 [英] JavaFX: Change application language on the run

查看:86
本文介绍了JavaFX:在运行时更改应用程序语言的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用FXML中描述的核心组件制作JavaFX桌面应用程序,我想为用户提供更改语言的选项。但是,一旦从FXML加载了组件,我就没有找到任何改变语言的直接方法。

I am making JavaFX desktop application with core components described in FXML and I would like to offer user the option to change the language. However I have not find any direct way how to change the language once the component has been loaded from the FXML.

问题是有没有任何标准方法如何处理在JavaFX中切换语言。

The question is is there any standard way how to deal with switching the language in JavaFX.

推荐答案

你可以这样做。在您的回答中,您可能希望将其实现为单例,或者使用DI框架在任何需要的地方注入单个实例:

You can do something like this. As in your answer, you would either want to implement this as a singleton, or use a DI framework to inject a single instance wherever you need it:

public class ObservableResourceFactory {

    private ObjectProperty<ResourceBundle> resources = new SimpleObjectProperty<>();
    public ObjectProperty<ResourceBundle> resourcesProperty() {
        return resources ;
    }
    public final ResourceBundle getResources() {
        return resourcesProperty().get();
    }
    public final void setResources(ResourceBundle resources) {
        resourcesProperty().set(resources);
    }

    public StringBinding getStringBinding(String key) {
        return new StringBinding() {
            { bind(resourcesProperty()); }
            @Override
            public String computeValue() {
                return getResources().getString(key);
            }
        };
    }
}

现在你可以做以下事情:

Now you can do things like:

ObservableResourceFactory resourceFactory = .... ;

resourceBundle.setResources(...);

Label greetingLabel = new Label();
greetingLabel.textProperty().bind(resourceFactory.getStringBinding("greeting"));

任何时候用

resourceFactory.setResources(...);

将导致标签更新其文本。

will cause the label to update its text.

这是一个SSCCE(对于将 ResourceBundle 强制转换为单个可运行类的极其难看的方式而道歉...)

Here's an SSCCE (with apologies for the extremely ugly way of forcing a ResourceBundle into a single runnable class...)

import java.util.ListResourceBundle;
import java.util.Locale;
import java.util.ResourceBundle;

import javafx.application.Application;
import javafx.beans.binding.StringBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class ResourceBundleBindingExample extends Application {

    private static final String RESOURCE_NAME = Resources.class.getTypeName() ;

    private static final ObservableResourceFactory RESOURCE_FACTORY = new ObservableResourceFactory();

    static {
        RESOURCE_FACTORY.setResources(ResourceBundle.getBundle(RESOURCE_NAME));
    }

    @Override
    public void start(Stage primaryStage) {
        ComboBox<Locale> languageSelect = new ComboBox<>();
        languageSelect.getItems().addAll(Locale.ENGLISH, Locale.FRENCH);
        languageSelect.setValue(Locale.ENGLISH);
        languageSelect.setCellFactory(lv -> new LocaleCell());
        languageSelect.setButtonCell(new LocaleCell());

        languageSelect.valueProperty().addListener((obs, oldValue, newValue) -> {
            if (newValue != null) {
                RESOURCE_FACTORY.setResources(ResourceBundle.getBundle(RESOURCE_NAME, newValue));
            }
        });

        Label label = new Label();
        label.textProperty().bind(RESOURCE_FACTORY.getStringBinding("greeting"));

        BorderPane root = new BorderPane(null, languageSelect, null, label, null);
        root.setPadding(new Insets(10));
        Scene scene = new Scene(root, 400, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static class LocaleCell extends ListCell<Locale> {
        @Override
        public void updateItem(Locale locale, boolean empty) {
            super.updateItem(locale, empty);
            if (empty) {
                setText(null);
            } else {
                setText(locale.getDisplayLanguage(locale));
            }
        }
    }

    public static class ObservableResourceFactory {

        private ObjectProperty<ResourceBundle> resources = new SimpleObjectProperty<>();
        public ObjectProperty<ResourceBundle> resourcesProperty() {
            return resources ;
        }
        public final ResourceBundle getResources() {
            return resourcesProperty().get();
        }
        public final void setResources(ResourceBundle resources) {
            resourcesProperty().set(resources);
        }

        public StringBinding getStringBinding(String key) {
            return new StringBinding() {
                { bind(resourcesProperty()); }
                @Override
                public String computeValue() {
                    return getResources().getString(key);
                }
            };
        }

    }

    public static class Resources extends ListResourceBundle {

        @Override
        protected Object[][] getContents() {
            return new Object[][] {
                    {"greeting", "Hello"}
            };
        }

    }

    public static class Resources_fr extends ListResourceBundle {

        @Override
        protected Object[][] getContents() {
            return new Object[][] {
                    {"greeting", "Bonjour"}
            };
        }

    }

    public static void main(String[] args) {
        launch(args);
    }
}

这篇关于JavaFX:在运行时更改应用程序语言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆