Search code examples
javaswinglook-and-feel

SwingUtilities.updateComponentTreeUI() not changing JFrames titlebar


Environment:

Using Netbeans 8.1

Oracle JDK 1.8

Win 10 pro

Context:

A GUI with a JCheckBoxMenuItem to change LookAndFeel(LAF) at runtime.

darkLAF=JTattoo's HiFi LAF

defaultLAF=Sun's Windows LAF(com.sun.java.swing.plaf.windows.WindowsLookAndFeel)

Problem:

  1. GUI launches(in EDT) with defaultLAF. User changes to darkLAF..the title bar should have changed..it doesn't.

  2. When the user switches back to defaultLAF, the JMenuItems(File and Edit) show greyer backgrounds not the defaultLAF style.

Screenshots:

  1. The launched defaultLAF

  2. upon switching to darkLAF

  3. user switched back to defaultLAF
  4. expected look for darkLAF

Code:

  1. Inside the itemStateChangeListener for JCheckBoxMenuItem

    try{
       if (checkBox.isSelected())                                                                 
          UIManager.setLookAndFeel(darkLookAndFeel);
       else
        UIManager.setLookAndFeel(defaultLookAndFeel);
    
    
    } catch (UnsupportedLookAndFeelException ex) {
       //handle err
    }
    
    //GUI is a class extending JFrame        
    SwingUtilities.updateComponentTreeUI(this);
    //some JFileChooser
    SwingUtilities.updateComponentTreeUI(fc);
    
    pack();
    

Catch:

  1. User shouldn't be asked to do a GUI restart.

Solution

  • It was a little bit hard, but I've found a solution.

    Steps you need to switch to the JTatto L&F

    1. Dispose window
    2. Set L&F
    3. Set window style of root pane to JRootPane.FRAME
    4. Update UI
    5. Make Frame undecorated
    6. Make Frame visible

    Steps you need to switch back to Windows L&F

    1. Dispose window
    2. Set L&F
    3. Update UI
    4. Make Frame decorated
    5. Make Frame visible

    Here is the code

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class MinFrame extends JFrame {
    
        public MinFrame() {
            super("Minimal-Frame-Application");
    
            // setup menu
            JMenuBar menuBar = new JMenuBar();
            JMenu menu = new JMenu("File");
            menu.setMnemonic('F');
            JMenuItem menuItem = new JMenuItem("Exit");
            menuItem.setMnemonic('x');
            menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, KeyEvent.ALT_MASK));
            menuItem.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent event) {
                    System.exit(0);
                }
            });
            menu.add(menuItem);
            menuBar.add(menu);
            setJMenuBar(menuBar);
    
            // setup widgets
            JPanel contentPanel = new JPanel(new BorderLayout());
            contentPanel.setBorder(BorderFactory.createEmptyBorder(0, 4, 4, 4));
            JScrollPane westPanel = new JScrollPane(new JTree());
            JEditorPane editor = new JEditorPane("text/plain", "Hello World");
            JScrollPane eastPanel = new JScrollPane(editor);
            JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, westPanel,eastPanel);
            splitPane.setDividerLocation(148);
            contentPanel.add(splitPane, BorderLayout.CENTER);
    
    
            AbstractButton winLF = new JButton("Windows");
            winLF.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    try {
                        MinFrame.this.dispose();
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                        SwingUtilities.updateComponentTreeUI(MinFrame.this.getRootPane());
    
                        MinFrame.this.setUndecorated(false);
                        MinFrame.this.setVisible(true);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            });
            AbstractButton customLF = new JButton("JTatto");
            customLF.addActionListener(new ActionListener() {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    try {
                        MinFrame.this.dispose();
                        UIManager.setLookAndFeel("com.jtattoo.plaf.smart.SmartLookAndFeel");
                        MinFrame.this.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
                        SwingUtilities.updateComponentTreeUI(MinFrame.this.getRootPane());
    
                        MinFrame.this.setUndecorated(true);
                        MinFrame.this.setVisible(true);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            });
    
            JPanel buttons = new JPanel();
            buttons.add(winLF);
            buttons.add(customLF);
            contentPanel.add(buttons, BorderLayout.SOUTH);
            setContentPane(contentPanel);
    
            // add listeners
            addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
    
            // show application
            setLocation(32, 32);
            setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            setSize(400, 300);
            setVisible(true);
        } // end CTor MinFrame
    
        public static void main(String[] args) {
            try {
                // select Look and Feel
    //            UIManager.setLookAndFeel("com.jtattoo.plaf.smart.SmartLookAndFeel");
                // start application
                new MinFrame();
            }
            catch (Exception ex) {
                ex.printStackTrace();
            }
        } // end main
    
    }