I am making a Java Swing Desktop Application. I am facing a problem while registering components to a localization object. In my app, for now, there is a MenuBar with 7 different Menus, a ToolBar composing of 7 ToolBars corresponding to the 7 Menus. One of the Menus contains a LanguageMenu as a dropdown inside of it, and there I can change between three languages. I set up a custom class Action Listener, and when I click on different languages the locale changes, and the GUI is changed.
The LanguageActionListener:
public class LanguageActionListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
Localization localization = Localization.getInstance();
switch (e.getActionCommand()) {
case "english":
localization.setLocal("en", "US");
break;
case "serbian":
localization.setLocal("sr", "BA");
break;
case "serbiancyrilic":
localization.setLocal("sr", "RS");
break;
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
localization.updateAll();
}
});
}
}
This Action Listener is just added to every button in the LanguageMenu.
The problem is that when I go to the Menus as they drop down, the localization changes are not applied. Basically every JMenuItem that I have is not changed, but is registered properly, as I would assume.
The Localization class:
public class Localization
{
public static Localization local = null;
public static HashMap<String, Component> hMaps = new HashMap<String, Component>();
private Locale currentLocale = null;
private ResourceBundle resource = null;
private String language = null;
private String country = null;
private Localization(String language, String country)
{
setLocal(language, country);
}
public static Localization getInstance(String language, String country)
{
if (local == null)
{
local = new Localization(language, country);
}
return local;
}
public static Localization getInstance()
{
if (local == null)
{
local = new Localization("en", "US");
}
return local;
}
public ResourceBundle getResource()
{
return this.resource;
}
public void setLocal(String language, String country)
{
this.language = language;
this.country = country;
this.currentLocale = new Locale(this.language, this.country);
ResourceBundle.clearCache();
this.resource = ResourceBundle.getBundle("ApplicationResources", this.currentLocale, CustomClassLoader.loadClass("ApplicationResources"));
}
public String getString(String title)
{
return this.resource.getString(title);
}
public void registerComponent(String title, Component components)
{
if (title != null)
{
hMaps.put(title, components);
}
}
public void updateText(String title)
{
Component comp = hMaps.get(title);
if (comp instanceof AbstractButton)
{
((AbstractButton) comp).setText(this.resource.getString(title));
}
}
public void updateAll()
{
Collection<String> c = hMaps.keySet();
Iterator<String> itr = c.iterator();
while (itr.hasNext())
{
String title = itr.next().toString();
Component comp = hMaps.get(title);
if (comp instanceof AbstractButton)
{
if (((AbstractButton) comp).getText() != "")
{
((AbstractButton) comp).setText(this.resource.getString(title));
}
((AbstractButton) comp).setToolTipText(this.resource.getString(title));
}
else if (comp instanceof JLabel)
{
if (((JLabel) comp).getText() != "")
{
((JLabel) comp).setText(this.resource.getString(title));
}
}
else if (comp instanceof Frame)
{
((Frame) comp).setTitle(this.resource.getString(title));
}
else if (comp instanceof Dialog)
{
((Dialog) comp).setTitle(this.resource.getString(title));
}
else if (comp instanceof JPanel)
{
if (((JPanel) comp).getBorder() instanceof TitledBorder)
{
((TitledBorder) ((JPanel) comp).getBorder()).setTitle(this.resource.getString(title));
}
}
}
}
}
Example code of EditMenu class:
public class EditMenu extends Menu{
private localization = null;
public EditMenu(){
localization = Localization.getInstance();
setText(localization.getString("menu.edit"));
localization.registerComponent("menu.edit", this);
undoMenuItem = new MenuItem(localization.getString("menu.edit.undo"));
localization.registerComponent("menu.edit.undo", undoMenuItem);
add(undoMenuItem)
}
}
would work without any problems, and the component is registered and upon changing the language the name of the Menu changes, while continuing...
Example code of the same EditMenu class:
undoMenuItem = new MenuItem(localization.getString("menu.edit.undo"));
localization.registerComponent("menu.edit.undo", undoMenuItem);
does not work, even though this is in the same Constructor of the EditMenu Class. The MenuItems have been added to the Menus, they work and their Action Listeners are doing everything they are supposed to do. Keep in mind the MenuItem is just an abstraction Class which inherits from the regular JMenuItem, where I just applied some changes, and basically in its constructer I did super(name), name being the parameter needed for the JMenuItems constructor. Also, in the LanguageMenu, which drops down in the WindowMenu, the LanguageMenus MenuItems change perfectly...The same goes for all the Custom JDialogs which appear when I click on the same MenuItems or corresponding ToolBar buttons.
The Menu Class:
public class Menu extends JMenu{
private static final long serialVersionUID = 1L;
public Menu() {
setFont(new Font("Arial", Font.PLAIN, 16));
setFocusable(false);
}
}
The MenuItem Class:
public class MenuItem extends JMenuItem{
private static final long serialVersionUID = 1L;
public MenuItem(String text)
{
super(text);
setFont(new Font("Arial", Font.PLAIN, 16));
}
}
I can add that I have three separate Property files which have the list of all of the string values for localization, and those files work properly.
I am having a problem understanding this, as everything else is updated, the ToolBars setToolTipText() method is localized as well and it works, but how do the MenuItems not get changed and updated.
I assumed the problem is with the way the UI is refreshing its visuals, but that is confusing as well, because how do the other components refresh well and the UI updates correctly. I have no way of changing the .jar as I have to use that specific .jar file, and I can't code onto it revalidate() and repaint() methods. I think that wouldn't change a thing.
If anyone has any ideas on what could be the issue, I would like some advice on how to go about this. I could also add further details, if needed. Thank you!!!