JavaFX:在运行时更改应用程序语言 [英] JavaFX: Change application language on the run
问题描述
我正在使用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屋!