3
votes

I know that there's a SwingUtilities.updateComponentTreeUI(Component c) method but it doesn't work perfectly. For example, I have a JFileChooser and the current look and feel is Windows, then I change the look and feel to Nimbus with SwingUtilities.updateComponentTreeUI(mainWindow), and the main window's style is changed correctly, but when I show the file chooser with the JFileChooser.showOpenDialog(Component parent) method, it's still in Windows look and feel. The same happens if I show a popup dialog with the JPopupMenu.show(Component invoker, int x, int y) method.

Any solution to this issue?

2
To be clear, you also adjusted the current L&F with UIManager.setLookAndFeel()?Duncan Jones

2 Answers

6
votes

Assuming that value is the class name of the new look-and-feel, here is the snippet to update all windows and sub-components:

public static void updateLAF(String value) {
    if (UIManager.getLookAndFeel().getClass().getName().equals(value)) {
        return;
    }
    try {
        UIManager.setLookAndFeel(value);
        for (Frame frame : Frame.getFrames()) {
            updateLAFRecursively(frame);
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (UnsupportedLookAndFeelException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public static void updateLAFRecursively(Window window) {
    for (Window childWindow : window.getOwnedWindows()) {
        updateLAFRecursively(childWindow);
    }
    SwingUtilities.updateComponentTreeUI(window);
}
5
votes

Calling SwingUtilities.updateComponentTreeUI(mainWindow) will only update the Swing components in the Swing hierarchy under mainWindow.

If you store the JFileChooser somewhere in your code (e.g. in a field of a class) without showing the JFileChooser the chooser will not be updated by the SwingUtilities.updateComponentTreeUI(mainWindow) call. You can work around this by adding a listener to the UIManager yourself and call SwingUtilities.updateComponentTreeUI(myStoredFileChooser) from that listener when the look-and-feel is changed.

Make sure you do not create a memory leak with this, e.g. let that listener only have a WeakReference to the JFileChooser (as the lifetime of the UIManager equals the lifetime of the JVM)