internationalization - teclado - ¿Cómo volver a cargar la pantalla cuando se cambian los idiomas en JavaFX?
configurar teclado mac español latino (4)
Bueno, soy principiante con java y fxml.
Estoy creando una aplicación y necesito cambiar el idioma de la pantalla. Tengo el archivo con claves internacionalizadas, pero no tengo idea, ya que recargo la pantalla con el idioma modificado. La aplicación tiene un menú donde tiene el idioma disponible. Solo quiero actualizar la pantalla cuando el usuario cambie de idioma.
el cambio sigue siendo manual, como se puede ver en el código: (Main.java):
public class Main extends Application {
private Locale locale = new Locale("en", "US");
private Image icon = new Image("picture.jpg");
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Home.fxml"), ResourceBundle.getBundle("label", locale));
Scene scene = new Scene(root);
stage.setTitle("GUI");
stage.getIcons().add(icon);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
Este código está en el controlador, cuando cambia el idioma:
@FXML
private void btnMenuLanguageEnglishAction(ActionEvent event) {
this.locale = new Locale("en", "US");
}
@FXML
private void btnMenuLanguagePortuguesAction(ActionEvent event) {
this.locale = new Locale("pt", "BR");
}
¿Cómo enviar esta configuración regional a main y actualizar la pantalla? como será el método que yo uso? He intentado algunos que vi aquí en el sitio, pero nadie respondió mi pregunta.
Logré resolver, el código:
Principal:
public class Main extends Application {
private static Locale locale = new Locale("pt", "BR");
private static Image icone = new Image("picture.jpg");
private Scene scene;
public static Stage stage;
/**
*
* @param st
* @throws Exception
*/
@Override
public void start(Stage st) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("Home.fxml"), ResourceBundle.getBundle("label", locale));
stage = st;
scene = new Scene(root);
stage.setTitle("GUI");
stage.getIcons().add(icone);
stage.setScene(scene);
stage.show();
}
public static Image getIcone() {
return icone;
}
public static Locale getLocale() {
return locale;
}
public static void setLocale(Locale locale) {
Main.locale = locale;
}
public void reload() throws IOException {
Parent root = FXMLLoader.load(getClass().getResource("Home.fxml"), ResourceBundle.getBundle("label", locale));
scene = new Scene(root);
stage.setTitle("GUI");
stage.getIcons().add(icone);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
el controlador:
@FXML
private void btnMenuLanguageEnglishAction(ActionEvent event) throws IOException {
Main.setLocale(new Locale("en", "US")); // change to english
Main.stage.close();
Main reload = new Main();
reload.reload();
}
@FXML
private void btnMenuLanguagePortuguesAction(ActionEvent event) throws IOException {
Main.setLocale(new Locale("pt", "BR")); // change to Portuguese;
Main.stage.close();
Main reload = new Main();
reload.reload();
}
pero todavía tiene un problema: el cambio de idioma puede ocurrir solo una vez, la segunda vez da un error fatal ... Esperanza que ayuda a alguien.
Lo sé, es una pregunta bastante antigua, pero soy nuevo en JavaFX y tenía el mismo problema. Aquí está mi solución final para cambiar el idioma en la aplicación. Puede que no sea ideal, pero funciona para mí. En el controlador, tengo ese método:
@FXML
private BorderPane root; //root pane
@FXML
private void changeLocale(ActionEvent event) throws IOException{
Scene scene = root.getScene();
if(event.getSource().equals(lang_en)){
scene.setRoot(FXMLLoader.load(getClass().getResource("Layout.fxml"),ResourceBundle.getBundle("resources/Bundle", Locale.ENGLISH))); // = new Locale("en")
}else if(event.getSource().equals(lang_cs)){
scene.setRoot(FXMLLoader.load(getClass().getResource("Layout.fxml"),ResourceBundle.getBundle("resources/Bundle", new Locale("cs", "CZ"))));
}else{
}
}
El método carga un nuevo cargador en mi escena (para cargar en el escenario también funciona).
Para el escenario completo ... Puedo cambiar el idioma actual con dos radiomenuitems en el menú, así que después de cargar el nuevo cargador (en el método "public void initialize (URL location, ResourceBundle resources)" en el controlador) cambio la selección de radiomenuitems con este modificador:
switch(resources.getLocale().getLanguage()){
case "en":
lang_en.setSelected(true);
break;
case "cs":
lang_cs.setSelected(true);
break;
default:
break;
}
Es simple y puede ser útil para otra persona que tendrá ese problema.
Aquí está mi implementación:
import javafx.fxml.FXMLLoader;
import javafx.geometry.NodeOrientation;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
/**
* Created by Fouad on 3/20/2015.
*/
public abstract class I18NController
{
private Stage primaryStage;
public void setPrimaryStage(Stage primaryStage){this.primaryStage = primaryStage;}
public Stage getPrimaryStage(){return primaryStage;}
public final void changeLanguage(I18NLanguage language) throws IOException
{
StateBundle stateBundle = new StateBundle();
onSaveState(stateBundle);
Locale locale = language.getLocale();
Locale.setDefault(locale);
ResourceBundle resourceBundle = getResourceBundle(locale);
URL fxml = getFXMLResource();
FXMLLoader loader = new FXMLLoader(fxml, resourceBundle);
Parent root = loader.load();
NodeOrientation nodeOrientation = language.getNodeOrientation();
root.setNodeOrientation(nodeOrientation);
primaryStage.setScene(new Scene(root));
primaryStage.sizeToScene();
I18NController newController = loader.getController();
newController.setPrimaryStage(primaryStage);
onLoadState(newController, language, resourceBundle, stateBundle);
}
protected abstract ResourceBundle getResourceBundle(Locale locale);
protected abstract URL getFXMLResource();
protected abstract void onSaveState(StateBundle stateBundle);
protected abstract void onLoadState(I18NController newController, I18NLanguage newLanguage, ResourceBundle resourceBundle, StateBundle stateBundle);
public static interface I18NLanguage
{
Locale getLocale();
NodeOrientation getNodeOrientation();
}
public static class StateBundle
{
private Map<String, Object> sMap = new HashMap<>();
StateBundle(){}
public void putData(String key, Object value)
{
sMap.put(key, value);
}
public <T> T getDate(String key, Class<T> type)
{
return type.cast(sMap.get(key));
}
}
}
Puede usar esta clase como clase base para el controlador, algo como esto:
JavaFXController.java:
public class JavaFXController extends I18NController implements Initializable
{
@FXML private DatePicker dpDate;
@FXML private RadioButton rdoArabic;
@FXML private RadioButton rdoEnglish;
// ...
@Override
public void initialize(URL location, ResourceBundle resources)
{
// ...
rdoEnglish.setOnAction(e ->
{
try
{
changeLanguage(AppSettings.Language.ENGLISH);
}
catch(IOException e1)
{
e1.printStackTrace();
}
});
rdoArabic.setOnAction(e ->
{
try
{
changeLanguage(AppSettings.Language.ARABIC);
}
catch(IOException e1)
{
e1.printStackTrace();
}
});
}
// ...
@Override
protected ResourceBundle getResourceBundle(Locale locale)
{
return ResourceBundle.getBundle("com//gui/resources/JavaFXResourceBundle", locale, new UTF8Control());
}
@Override
protected URL getFXMLResource()
{
return getClass().getResource("resources/JavaFXDocument.fxml");
}
@Override
protected void onSaveState(StateBundle stateBundle)
{
LocalDate localDate = dpDate.getValue();
boolean isRdoArabicSelected = rdoArabic.isSelected();
boolean isRdoEnglishSelected = rdoEnglish.isSelected();
stateBundle.putData("localDate", localDate);
stateBundle.putData("isRdoArabicSelected", isRdoArabicSelected);
stateBundle.putData("isRdoEnglishSelected", isRdoEnglishSelected);
}
@Override
protected void onLoadState(I18NController newController, I18NLanguage newLanguage, ResourceBundle resourceBundle, StateBundle stateBundle)
{
JavaFXController controller = (JavaFXController) newController;
controller.getPrimaryStage().setTitle(resourceBundle.getString("window.title"));
NodeOrientation nodeOrientation = newLanguage.getNodeOrientation();
LocalDate localDate = stateBundle.getDate("localDate", LocalDate.class);
boolean isRdoArabicSelected = stateBundle.getDate("isRdoArabicSelected", Boolean.class);
boolean isRdoEnglishSelected = stateBundle.getDate("isRdoEnglishSelected", Boolean.class);
controller.dpDate.setValue(localDate);
controller.rdoArabic.setSelected(isRdoArabicSelected);
controller.rdoEnglish.setSelected(isRdoEnglishSelected);
}
}
AppSettings.java:
import com.parmajeyat.autobooking.gui.I18NController;
import javafx.geometry.NodeOrientation;
import java.util.Locale;
/**
* Created by Fouad on 2/7/2015.
*/
public final class AppSettings
{
private static final class Locales
{
public static final Locale SAUDI_AR_LOCALE = new Locale.Builder().setLanguageTag("ar-SA-u-nu-arab").build(); // nu is for numbers
public static final Locale SAUDI_EN_LOCALE = new Locale("en", "SA");
}
public static enum Language implements I18NController.I18NLanguage
{
ARABIC(Locales.SAUDI_AR_LOCALE, NodeOrientation.RIGHT_TO_LEFT),
ENGLISH(Locales.SAUDI_EN_LOCALE, NodeOrientation.LEFT_TO_RIGHT);
private Locale locale;
private NodeOrientation nodeOrientation;
Language(Locale locale, NodeOrientation nodeOrientation)
{
this.locale = locale;
this.nodeOrientation = nodeOrientation;
}
public Locale getLocale(){return locale;}
public NodeOrientation getNodeOrientation(){return nodeOrientation;}
}
}
UTF8Control.java:
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Locale;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
/**
* Created by Fouad on 2/1/2015.
*/
public class UTF8Control extends ResourceBundle.Control
{
public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException, IOException
{
// The below is a copy of the default implementation.
String bundleName = toBundleName(baseName, locale);
String resourceName = toResourceName(bundleName, "properties");
ResourceBundle bundle = null;
InputStream stream = null;
if(reload)
{
URL url = loader.getResource(resourceName);
if(url != null)
{
URLConnection connection = url.openConnection();
if(connection != null)
{
connection.setUseCaches(false);
stream = connection.getInputStream();
}
}
}
else
{
stream = loader.getResourceAsStream(resourceName);
}
if(stream != null)
{
try
{
// Only this line is changed to make it to read properties files as UTF-8.
bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8"));
}
finally
{
stream.close();
}
}
return bundle;
}
}
Utilice el enlace con su etiqueta (etiqueta, texto, título del panel, etc.).