JavaFX: Change application language on the run

前端 未结 3 1144
情话喂你
情话喂你 2020-12-13 11:30

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 d

3条回答
  •  眼角桃花
    2020-12-13 11:46

    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 resources = new SimpleObjectProperty<>();
        public ObjectProperty 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"));
    

    And any time you update the resource with

    resourceFactory.setResources(...);
    

    will cause the label to update its text.

    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 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 {
            @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 resources = new SimpleObjectProperty<>();
            public ObjectProperty 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);
        }
    }
    

提交回复
热议问题