Страницы

Поиск по вопросам

понедельник, 15 июля 2019 г.

Как реализовать динамичную смену языка? JavaFX

Хочу реализовать адекватное переключение языков в приложении, чтобы сразу после нажатие кнопки "сменить язык" все компоненты автоматически поменяли название. Пока что сделал так:
public void setEnglish(ActionEvent actionEvent) {
Main.locale = new Locale("en"); rb = ResourceBundle.getBundle("ua.javaFX.myprograms.address_book.bundles.Locale", Main.locale);
mainStage.setTitle(rb.getString("key.address_book")); btnAdd.setText(rb.getString("key.add")); btnEdit.setText(rb.getString("key.change")); btnDelete.setText(rb.getString("key.delete")); btnSearch.setText(rb.getString("key.search")); btnLanguage.setText(rb.getString("key.language")); btnEnglish.setText(rb.getString("key.english")); btnRussian.setText(rb.getString("key.russian")); }
Суть вопроса: есть какой-то цивилизованный способ для обновления содержания страницы? Если я не ошибаюсь, в SWING таким является:
SwingUtilities.updateComponentTreeUI(frame);


Ответ

Для того, чтобы вам сделать такое, необходимо использовать bindings
Вам нужна resources factory :
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); } }; } }
Далее, в своем коде можете написать такое
ObservableResourceFactory resourceFactory = .... ;
resourceBundle.setResources(...);
Label greetingLabel = new Label(); greetingLabel.textProperty().bind(resourceFactory.getStringBinding("greeting"));
И в любой момент, когда вы будет обновлять ресурсы
resourceFactory.setResources(...);
на лейбле текст будет меняться.
Вот пример, как это работает
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); } }
P.S. ответ взят с английского SO

Комментариев нет:

Отправить комментарий