Search code examples
javaswingbuttonborderlook-and-feel

Is it possible to retain button's border after changing the Look and Feel? (Java Swing)


I am currently working on a project in which users are allowed to choose a Look and Feel. However, when users choose another Look and Feel and change it back to the original CrossPlatformLookAndFeel, the borders of buttons disappear.

code:

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

public class SSCCE {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                final JFrame frame = new JFrame();
                final JButton button = new JButton("Button");
                button.setBorder(LineBorder.createBlackLineBorder());
                button.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent ev) {
                        try{
                        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
                            SwingUtilities.updateComponentTreeUI(frame);
                            UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
                            SwingUtilities.updateComponentTreeUI(frame);
                        } catch (Exception ex) {
                            System.out.println(ex.getMessage());
                        }
                    }
                });
                //
                frame.setLayout(new FlowLayout(FlowLayout.CENTER));
                frame.add(button);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

As you see, the border disappears after you click the button.

So the question is: can the border be retained after changing the Look and Feel? I know the border will not appear in WindowsLookAndFeel, but is it possible to "reappear" after the Look and Feel is changed back to the default one?


Solution

  • Last time I checked, there were a variety of bugs in PLAFs that caused these types of odd behavior. Especially when changing from the MetaL LAF (but a good swathe are related to Nimbus as well).

    The only reliable way to get the app. to change PLAFs is:

    • Serialize the user's choice of new PLAF (i.e. as a String of the fully qualified class name).
    • Launch a new process that calls the main(String[]), which would check for the serialized string of the new PLAF to use, and use it.
    • (Possibly pass the state of the current GUI to the new GUI.)
    • Close the current GUI.

    As you can see, quite a hassle to get an 'absolutely rock solid reliable' PLAF change.