2012-10-31 24 views
11

Ho provato a modificare le impostazioni locali in fase di esecuzione nella mia applicazione swing.
Ma non riesco a capire come dovrebbe funzionare, o non ci sono piani generali?Come cambiare lingua in fase di esecuzione in java swing

Posso solo pensare a due scelte:
1. Riavviare l'applicazione, non la migliore esperienza utente.
2. Creare un gestore di localizzazione in grado di registrare/annullare la registrazione dei componenti, in una modifica basta solo iterare tutti i componenti e modificare il testo.

Sia 1 che 2 sono scomodi.

Altre informazioni:
Per il momento l'orientamento non è un obiettivo.
L'applicazione è offuscata.

Esempio:

LocRes_en.properties:

 

    text1 = English text 

LocRes_ja.properties

 

    text1 = Japanese text 

ChangeLocale.java:

 

    import java.awt.EventQueue; 
    import java.awt.FlowLayout; 
    import java.awt.event.ActionEvent; 
    import java.awt.event.ActionListener; 
    import java.util.Locale; 
    import java.util.ResourceBundle; 

    import javax.swing.JButton; 
    import javax.swing.JFrame; 
    import javax.swing.JLabel; 

    public class ChangeLocale { 

     private JFrame frame; 

     public static void main(String[] args) { 
      EventQueue.invokeLater(new Runnable() { 
       public void run() { 
        try { 
         ChangeLocale window = new ChangeLocale(); 
         window.frame.setVisible(true); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
      }); 
     } 

     public ChangeLocale() { 
      initialize(); 
     } 

     private void initialize() { 
      frame = new JFrame(); 
      frame.setBounds(100, 100, 450, 300); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      FlowLayout flowLayout = new FlowLayout(FlowLayout.CENTER, 5, 5); 
      frame.getContentPane().setLayout(flowLayout); 

      JButton btnChangeLoc = new JButton("Change Locale"); 
      frame.getContentPane().add(btnChangeLoc); 

      final JLabel lblLabel1 = new JLabel("New label"); 
      frame.getContentPane().add(lblLabel1); 
      Locale.setDefault(new Locale("en")); 
      ResourceBundle r = ResourceBundle.getBundle("LocRes"); 
      lblLabel1.setText(r.getString("text1")); 

      btnChangeLoc.addActionListener(new ActionListener() { 
       public void actionPerformed(ActionEvent e) { 
        Locale.setDefault(new Locale("ja")); 
        ResourceBundle r = ResourceBundle.getBundle("LocRes"); 
        // Manually iterate through all components :(
        lblLabel1.setText(r.getString("text1")); 
        // 
       } 
      }); 
     } 
    }
+0

[mai avuto bisogno, ma ci sono devono essere som Esempi sul caricamento delle proprietà su HashMap o List] (http://java2s.com/Tutorial/Java/0220__I18N/Catalog0220__I18N.htm) – mKorbel

risposta

2

Ho fatto qualcosa di simile una volta. Sebbene il mio compito fosse più semplice: si trattava di un'applicazione per la barra delle applicazioni, quindi ho dovuto solo modificare il testo delle voci di menu.

Ma nel tuo caso penso che sia fattibile. Per prima cosa, evita le stringhe hard-coded nel tuo livello GUI. Crea una classe che modifica le impostazioni internazionali e poi itera su tutti i fotogrammi visibili e scende a tutti i pannelli e componenti e cambia il testo scritto su di essi. L'unico problema che posso aspettarmi qui è il testo disegnato su tela.

3

Ho implementato questo con ResourceBundles e un EventBus.

Quando le impostazioni internazionali vengono modificate, EventBus attiva un localeChangedEvent. Tutte le finestre JFrame che hanno stringhe localizzate devono quindi iscriversi a questo evento. Devono anche implementare un metodo changeLocale() che viene eseguito quando viene ricevuto l'evento.

In questo metodo tutte le stringhe verranno aggiornate alle impostazioni internazionali correnti.

public void changeLocale(ResourceBundle rb) { 
    lblLabel1.setText(rb.getString("text1")); 
    lblLabel2.setText(rb.getString("text2")); 
    ... 
} 
0

Definire una GUI e una casella combinata con le lingue supportate. Aggiungi un ItemListener così quando la casella combinata viene cambiata, i testi vengono aggiornati.

LanguageGUIClient.java:

import javax.swing.*; 

public class LanguageGUIClient 
{ 
    public static void main(String[] arguments) throws Exception 
    { 
     UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 

     SwingUtilities.invokeLater(() -> 
     { 
      LanguageGUI languageGUI = new LanguageGUI(); 
      languageGUI.setVisible(true); 
     }); 
    } 
} 

LanguageGUI.java:

import javax.swing.*; 
import java.util.Locale; 
import java.util.ResourceBundle; 

public class LanguageGUI extends JFrame 
{ 
    public static ResourceBundle resourceBundle; 

    private JPanel rootPanel; 
    private JComboBox<Locale> languageComboBox; 
    private JLabel languageLabel; 

    public LanguageGUI() 
    { 
     configureFrameProperties(); 
    } 

    private void configureFrameProperties() 
    { 
     add(rootPanel); 
     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     setLocationRelativeTo(null); 
     languageComboBox.addItem(Locale.US); 
     languageComboBox.addItem(Locale.GERMANY); 
     languageComboBox.addItem(Locale.FRANCE); 
     setTexts(); 
     languageComboBox.addItemListener(itemEvent -> setTexts()); 
     setSize(300, 100); 
    } 

    private void setTexts() 
    { 
     Locale locale = languageComboBox.getItemAt(languageComboBox.getSelectedIndex()); 
     resourceBundle = ResourceBundle.getBundle("Bundle", locale); 
     setTitle(resourceBundle.getString("application.title")); 
     languageLabel.setText(resourceBundle.getString("language") + ":"); 
     languageComboBox.setToolTipText(resourceBundle.getString("language.tooltip")); 
    } 
} 

Nota che sto usando IntelliJ's form designer in modo che il contenuto del file .form sono necessari pure.

LanguageGUI.form:

<?xml version="1.0" encoding="UTF-8"?> 
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="LanguageGUI"> 
    <grid id="27dc6" binding="rootPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> 
    <margin top="0" left="0" bottom="0" right="0"/> 
    <constraints> 
     <xy x="20" y="20" width="500" height="400"/> 
    </constraints> 
    <properties/> 
    <border type="none"/> 
    <children> 
     <component id="eb651" class="javax.swing.JComboBox" binding="languageComboBox"> 
     <constraints> 
      <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/> 
     </constraints> 
     <properties> 
      <toolTipText value=""/> 
     </properties> 
     </component> 
     <vspacer id="977c1"> 
     <constraints> 
      <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/> 
     </constraints> 
     </vspacer> 
     <component id="e59f" class="javax.swing.JLabel" binding="languageLabel"> 
     <constraints> 
      <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> 
     </constraints> 
     <properties> 
      <text value=""/> 
     </properties> 
     </component> 
    </children> 
    </grid> 
</form> 

Inoltre, è necessario creare i file di bundle rispettive risorse nella directory risorse:

Il risultato è un GUI con una casella combinata che consente di modificare la lingua subito:

Problemi correlati