2014-01-16 92 views
3

那麼,我是初學java和fxml。如何在JavaFX中更改語言時重新加載屏幕?

我創建了一個應用程序,需要更改屏幕語言。我有國際化的鑰匙文件,但我不知道用更改後的語言重新加載屏幕。 應用程序有一個可用語言的菜單。當用戶改變語言時,我只想刷新屏幕。

變化仍然是手動,你可以在代碼中看到:(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); 
} 

此代碼是在控制器上,當改變語言:

@FXML 
private void btnMenuLanguageEnglishAction(ActionEvent event) { 
    this.locale = new Locale("en", "US"); 
} 

@FXML 
private void btnMenuLanguagePortuguesAction(ActionEvent event) { 
    this.locale = new Locale("pt", "BR"); 
} 

怎麼送這個區域設置爲主並刷新屏幕? 作爲將使用的方法?我嘗試了一些我在網站上看到的,但沒有人回答我的問題。

回答

0

我設法解決,代碼:

主營:

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); 
} 

} 

控制器:

@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(); 
} 

,但仍然有一個問題:只能出現一次語言的變化,第二次給了致命的錯誤...希望能幫助別人。

2

我知道,這是一個相當古老的問題,但我是JavaFX的新手,而且我也遇到了同樣的問題。 這是我在應用程序中更改語言的最終解決方案。它可能不是理想的,但它適用於我。 在控制器我有一個方法:

@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{ 
     } 
} 

的方法加載新的加載到我的場景(加載到舞臺也適用)。

對於完整的場景...我可以用菜單中的兩個radiomenuitems更改當前語言,因此在加載新加載器(在控制器中的「public void initialize(URL位置,ResourceBundle資源)」方法)中,我更改了radiomenuitems使用此開關:

switch(resources.getLocale().getLanguage()){ 
     case "en": 
      lang_en.setSelected(true); 
      break; 
     case "cs": 
      lang_cs.setSelected(true); 
      break; 
     default: 
      break; 
     } 

這很簡單,可能對其他有此問題的人有用。

3

這是我實現:

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)); 
     } 
    } 
} 

你可以使用這個類作爲基類控制器,這樣的事情:

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/stackoverflow/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; 
    } 
} 
0

使用與標籤(Label,Text,TitledPane等)的綁定。

相關問題