7

我正在构建一个 java 应用程序,我想在运行时使用这些单选按钮更改应用程序的主题(外观)。我不知道该怎么做!

Java 应用程序改变外观

提前致谢!

4

4 回答 4

8

您可以通过调用SwingUtilities.updateTreeComponentUI(frame)和传递容器组件来做到这一点。请注意,它并不总是有效的。所以是这样的:

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

此方法将当前的 LaF 更改为系统。

编辑:

JRadioMenuItem通过演示更改 LaF :

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

            }
        });
    }
}
于 2013-08-24T13:19:21.397 回答
8

您只需要使用UIManager.LookAndFeelInfo[]来存储 available LookAndFeel,然后使用UIManager.setLookAndFeel(LookAndFeelClassName)来设置并在此之后调用SwingUtilities.updateComponentTreeUI(frameReference)

编辑 :

pack在最后调用JFrame/JWindow/JDialog(父容器),正如Swing Lord@AndrewThompson 所指定的那样。

请看一下这个小例子:

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

编辑 2:

更新代码示例以包括动态LookAndFeels添加JRadioButtonMenuItem。虽然请注意,如果您使用Action而不是 an会更好ActionListener,我使用它只是为了合并前面代码中的更改:-)

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);
    }
}
于 2013-08-24T13:22:52.570 回答
1

好吧,考虑到当前选择了 Nimbus,我假设您想将 LAF 更改为 Nimbus?如果是这样,您将需要这样做:

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

如果要查看当前安装的所有 LAF,可以使用UIManager.getInstalledLookAndFeels();. 有关更多信息,请考虑阅读

于 2013-08-24T13:19:29.693 回答
0

这是我的:

当用户单击 JMenuItem 或您选择的其他内容时发生 Action 事件时,您应该调用此方法。

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);
       }
}
于 2015-07-04T00:33:59.697 回答