Question

I am building a java app and I want to change the theme(look and feel) of application at runtime with these radio buttons. I do not know how to do this!

Java Application Changing Look and feel

Thanks in advance!

Was it helpful?

Solution

You can do that by calling SwingUtilities.updateTreeComponentUI(frame) and passing container component. Be aware that it won't be efficient always. So something like this:

public static void changeLaf(JFrame frame) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException
                | IllegalAccessException | UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }
        SwingUtilities.updateComponentTreeUI(frame);
    }

This method changes current LaF to systems.

EDIT:

Changing LaF via JRadioMenuItem demo:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableModel;

public class LafDemo {

    public static void changeLaf(JFrame frame, String laf) {
        if (laf.equals("metal")) {
            try {
                UIManager.setLookAndFeel(UIManager
                        .getCrossPlatformLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException
                    | IllegalAccessException | UnsupportedLookAndFeelException e) {
                e.printStackTrace();
            }
        }
        if (laf.equals("nimbus")) {
            try {
                UIManager
                        .setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
            } catch (ClassNotFoundException | InstantiationException
                    | IllegalAccessException | UnsupportedLookAndFeelException e) {
                e.printStackTrace();
            }
        }
        if (laf.equals("system")) {
            try {
                UIManager.setLookAndFeel(UIManager
                        .getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException
                    | IllegalAccessException | UnsupportedLookAndFeelException e) {
                e.printStackTrace();
            }
        }

        SwingUtilities.updateComponentTreeUI(frame);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                final JFrame frame = new JFrame();
                JPanel panel = new JPanel();
                JButton btnDemo = new JButton("JButton");
                JSpinner spnDemo = new JSpinner();
                JComboBox<String> cmbDemo = new JComboBox<String>();
                cmbDemo.addItem("One");
                cmbDemo.addItem("Two");
                cmbDemo.addItem("Three");

                JMenuBar mBar = new JMenuBar();
                frame.setJMenuBar(mBar);
                JMenu mnuLaf = new JMenu("Look and feel");
                JRadioButtonMenuItem mniNimbus = new JRadioButtonMenuItem(
                        "Nimbus");
                JRadioButtonMenuItem mniMetal = new JRadioButtonMenuItem(
                        "Metal");
                JRadioButtonMenuItem mniSystem = new JRadioButtonMenuItem(
                        "Systems");

                ButtonGroup btnGroup = new ButtonGroup();
                btnGroup.add(mniNimbus);
                btnGroup.add(mniMetal);
                btnGroup.add(mniSystem);
                mBar.add(mnuLaf);
                mnuLaf.add(mniNimbus);
                mnuLaf.add(mniMetal);
                mnuLaf.add(mniSystem);

                mniNimbus.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        changeLaf(frame, "nimbus");
                    }
                });
                mniMetal.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        changeLaf(frame, "metal");
                    }
                });
                mniSystem.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        changeLaf(frame, "system");
                    }
                });

                DefaultTableModel model = new DefaultTableModel(
                        new Object[][] {}, new String[] { "First", "Second" });
                model.addRow(new Object[] { "Some text", "Another text" });
                JTable table = new JTable(model);
                panel.add(btnDemo);
                panel.add(spnDemo);
                panel.add(cmbDemo);
                frame.add(panel, BorderLayout.NORTH);
                frame.add(new JScrollPane(table), BorderLayout.CENTER);
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                frame.pack();
                frame.setVisible(true);

            }
        });
    }
}

OTHER TIPS

You simply need to use the UIManager.LookAndFeelInfo[] to store the available LookAndFeel, then use UIManager.setLookAndFeel(LookAndFeelClassName) to set and after this do call SwingUtilities.updateComponentTreeUI(frameReference)

EDIT :

Do call pack on JFrame/JWindow/JDialog(parent container) at the end, as very much specified by the Swing Lord @AndrewThompson.

Please have a look at this small example :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class LookAndFeelDemo {

    private JFrame frame;
    private JButton button;
    private int counter;
    private Timer timer;
    private JLabel lafNameLabel;

    private UIManager.LookAndFeelInfo[] lafs;

    public LookAndFeelDemo() {
        lafs = UIManager.getInstalledLookAndFeels();
        counter = 0;
    }

    private ActionListener eventActions = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {

            if (ae.getSource() == timer) {
                counter %= lafs.length;
                try {
                    UIManager.setLookAndFeel(lafs[counter].getClassName());
                } catch(Exception e) {e.printStackTrace();}
                SwingUtilities.updateComponentTreeUI(frame);
                lafNameLabel.setText(lafs[counter++].getName());
                frame.pack();
            } else if (ae.getSource() == button) {
                if (timer.isRunning()) {
                    timer.stop();
                    button.setText("Start");
                } else {
                    timer.start();
                    button.setText("Stop");
                }
            }
        }
    };

    private void displayGUI() {
        frame = new JFrame("Swing Worker Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane =  new JPanel();
        lafNameLabel = new JLabel("Nothing to display yet...", JLabel.CENTER);
        button = new JButton("Stop");
        button.addActionListener(eventActions);
        contentPane.add(lafNameLabel);
        contentPane.add(button);
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosed(WindowEvent e) {
                timer.stop();
            }
        });
        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        timer = new Timer(1000, eventActions);
        timer.start();
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new LookAndFeelDemo().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}

EDIT 2 :

Updating the code example to include adding LookAndFeels from JRadioButtonMenuItem on the fly. Though please, be advised, it would be much better if you use Action instead of an ActionListener, I used it only to incorporate the changes in the previous code :-)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class LookAndFeelDemo {

    private JFrame frame;
    private JButton button;
    private int counter;
    private Timer timer;
    private JLabel lafNameLabel;
    private ButtonGroup bg;
    private JRadioButtonMenuItem[] radioItems;

    private UIManager.LookAndFeelInfo[] lafs;

    public LookAndFeelDemo() {
        lafs = UIManager.getInstalledLookAndFeels();        
        counter = 0;
    }

    private ActionListener eventActions = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {

            if (ae.getSource() == timer) {
                counter %= lafs.length;
                try {
                    UIManager.setLookAndFeel(lafs[counter].getClassName());
                } catch(Exception e) {e.printStackTrace();}
                SwingUtilities.updateComponentTreeUI(frame);
                lafNameLabel.setText(lafs[counter++].getName());
                frame.pack();
            } else if (ae.getSource() == button) {
                if (timer.isRunning()) {
                    timer.stop();
                    button.setText("Start");
                } else {
                    timer.start();
                    button.setText("Stop");
                }
            } else if (ae.getSource() instanceof JRadioButtonMenuItem) {
                JRadioButtonMenuItem radioItem = (JRadioButtonMenuItem) ae.getSource();
                String lafName = radioItem.getActionCommand();
                System.out.println("LAF Name : " + lafName);
                for (int i = 0; i < radioItems.length; i++) {
                    if (lafName.equals(radioItems[i].getActionCommand())) {
                        setApplicationLookAndFeel(lafs[i].getClassName());
                    }
                }
            }
        }

        private void setApplicationLookAndFeel(String className) {
            try {
                UIManager.setLookAndFeel(className);
            } catch (Exception e) {e.printStackTrace();}
            SwingUtilities.updateComponentTreeUI(frame);
            frame.pack();
        }
    };

    private void displayGUI() {
        frame = new JFrame("Swing Worker Example");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel contentPane =  new JPanel();
        lafNameLabel = new JLabel("Nothing to display yet...", JLabel.CENTER);
        button = new JButton("Start");
        button.addActionListener(eventActions);
        contentPane.add(lafNameLabel);
        contentPane.add(button);
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosed(WindowEvent e) {
                timer.stop();
            }
        });

        frame.setJMenuBar(getMenuBar());
        frame.setContentPane(contentPane);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        timer = new Timer(1000, eventActions);
    }

    private JMenuBar getMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        JMenu lookAndFeelMenu = new JMenu("Look And Feels");

        bg = new ButtonGroup();
        radioItems = new JRadioButtonMenuItem[lafs.length];
        for (int i = 0; i < radioItems.length; i++) {
            radioItems[i] = new JRadioButtonMenuItem(lafs[i].getName());
            radioItems[i].addActionListener(eventActions);
            bg.add(radioItems[i]);
            lookAndFeelMenu.add(radioItems[i]);
        }

        menuBar.add(lookAndFeelMenu);

        return menuBar;
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                new LookAndFeelDemo().displayGUI();
            }
        };
        EventQueue.invokeLater(runnable);
    }
}

Well, considering Nimbus is currently selected, I am going to assume that you want to change the LAF to Nimbus? If so, you will need to do this:

UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");

If you want to see all of the LAFs that are currently installed, you could use UIManager.getInstalledLookAndFeels();. For more information, consider reading this

Here's mine:

You should call this method when a Action event occurs when the user clicks on a JMenuItem or something else of your choice.

private void changeLookAndFeel() {

         final LookAndFeelInfo[] list = UIManager.getInstalledLookAndFeels();

                final List<String> lookAndFeelsDisplay = new ArrayList<>();
                final List<String> lookAndFeelsRealNames = new ArrayList<>();

                for (LookAndFeelInfo each : list) {
                    lookAndFeelsDisplay.add(each.getName());
                    lookAndFeelsRealNames.add(each.getClassName());
                }

                if (lookAndFeelsDisplay.size() != lookAndFeelsRealNames.size()) {
                    throw new InternalError();
                }

                String changeSpeed = (String) JOptionPane.showInputDialog(this, "Choose Look and Feel Here\n(these are all available on your system):", "Choose Look And Feel", JOptionPane.QUESTION_MESSAGE, null, lookAndFeelsDisplay.toArray(), null);

                boolean update = false;
                if (changeSpeed != null && changeSpeed.length() > 0) {
                    for (int a = 0; a < lookAndFeelsDisplay.size(); a++) {
                        if (changeSpeed.equals(lookAndFeelsDisplay.get(a))) {
                            try {
                                UIManager.setLookAndFeel(lookAndFeelsRealNames.get(a)); //re update with correct class name String
                                this.whichLookAndFeel = changeSpeed;
                                update = true;
                            }
                            catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                                err.println(ex);
                                ex.printStackTrace();
                                Logger.getLogger(Starfighter.class.getName()).log(Level.SEVERE, null, ex);
                                }
                            }
                        }
                    }

                    if (update) {
                        int width = 800;
                        int height = 625;
                        if (UIManager.getLookAndFeel().getName().equals("CDE/Motif")) {
                            height += 12;
                        }

                        this.setSize(width, height);
                        this.menuBar.updateUI();

             this.menuBar = new JMenuBar();
                menuBar.updateUI();
                this.setJMenuBar(menuBar);
       }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top