Change the look and feel of java application on runtime (IDE: Netbeans)
Asked Answered
S

4

8

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!

Sisk answered 24/8, 2013 at 13:5 Comment(1)
I hope the updated answer will help you to get an idea, as to how to select LookAndFeel using Menus :-)Rocky
L
8

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);

            }
        });
    }
}
Lananna answered 24/8, 2013 at 13:19 Comment(8)
I just want to change look and feel through a radio button. suppose: if(JRadioButton1.isSelected()){ //then change the look and feel }else if(JRadioButton2.isSelected()){ //then change the other look and feel } and as so on.. how can i do that..?Sisk
Thanks dear! its working quite fine! but I have another problem with that! which is that you are creating a frame by JFrame frame = new JFrame(); and passes frame to method changeLaf(frame, string) But I have created a JFrame Form in my project and I want to pass that JFrame form in that method, I don't know how to do that!Sisk
@RafiAbro You mean you extended your class with JFrame? I don't understand.Lananna
@RafiAbro Then just pass this keyword instead of frame.Lananna
I tried this keyword but it shows error that non static variable can not be referenced in a static method..!Sisk
@RafiAbro Then make changeLaf method as non-static. Just: public void changeLaf(JFrame frame, String laf) {....}Lananna
let us continue this discussion in chatSisk
Its giving same error that non static variable can not be referenced in a static method even I am removing static from a method changeLaf!Sisk
R
8

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);
    }
}
Rocky answered 24/8, 2013 at 13:22 Comment(5)
@brano88 : THANK YOU for the edit :-) I just don't like Anonymous Inner Classes that is why I kept it that way, and added the functionality to the JButton which was doing nothing before :-) But atleast now, it will stop no matter what happens :-)Rocky
A call to pack() after PLAF change might also be appropriate. The Nested Layout Example leaves the choice to the user.Zeeland
@AndrewThompson : Ahha, something new for me to learn on the topic :-) Thankyou for sharing and KEEP SMILING :-) Never looked at that JCheckBox for selecting pack() :( It did accommodated the new effects a bit more nicely after calling pack() :-)Rocky
@nIcEcOw I mainly put it there to help underline the fact that 'null layouts' can fail due to the end user (or their JRE) forcing another PLAF than the programmer intended. OTOH 'null layouts' can fail when the direction of the breeze changes, so I'm not sure my point was well made. ;)Zeeland
@nIcE cOw who knows :-) my hat down, glad and welcome hereCorking
P
1

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

Pizzicato answered 24/8, 2013 at 13:19 Comment(1)
I just want to change look and feel through a radio button. suppose: if(JRadioButton1.isSelected()){ //then change the look and feel }else if(JRadioButton2.isSelected()){ //then change the other look and feel } and as so on.. how can i do that..?Sisk
R
0

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);
       }
}
Redbreast answered 4/7, 2015 at 0:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.