Swing應用程序如果是在開源的Look&&Feel 之間切換,感覺很容易,但是如果把應用程序在開源外觀下切換到系統默認的或者JDK自帶的外觀時,問題就來了。不是沒有標題欄,就是標題欄的外觀沒有改變,用的是系統的窗口裝飾。這些是因為在應用程序啟動時在main方法裡添加了這樣一句代碼造成的:
JFrame.setDefaultLookAndFeelDecorated(true);
目前解決這個問題的辦法就是先將 原來的JFrame dispose掉 ,然後在new一個 JFrame ,讓原來的frame 指向這個新的JFrame。不多說,看代碼比較直觀, 核心代碼如下:
初始化應用,initComponents()方法是NetBeans IDE生成的,就不貼了。
private static JFrame config; private Rectangle savedBounds; /** Creates new form Config */ public SkinChangeDemo() { initComponents(); } public SkinChangeDemo(boolean decor) { setUndecorated(decor); initComponents(); }
下面就是核心代碼:
private void saharaButtonActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: LookAndFeel old = UIManager.getLookAndFeel(); SubstanceSkin skin = new SaharaSkin(); if (old instanceof SubstanceLookAndFeel) { SubstanceLookAndFeel.setSkin(skin); } else { //如果不是Substance的外觀則切換為Substance外觀 changSkin(skin); } } private void nimbusButtonActionPerformed(java.awt.event.ActionEvent evt) { try { UIManager.setLookAndFeel(new NimbusLookAndFeel()); savedBounds = getBounds(); dispose(); config = null; config = new SkinChangeDemo(false); config.setBounds(savedBounds); config.setVisible(true); } catch (UnsupportedLookAndFeelException ex) { Logger.getLogger(SkinChangeDemo.class.getName()).log(Level.SEVERE, null, ex); } SwingUtilities.updateComponentTreeUI(this); } private void businessButtonActionPerformed(java.awt.event.ActionEvent evt) { LookAndFeel old = UIManager.getLookAndFeel(); SubstanceSkin skin = new BusinessSkin(); if (old instanceof SubstanceLookAndFeel) { SubstanceLookAndFeel.setSkin(skin); } else { //如果不是Substance的外觀則切換為Substance外觀 changSkin(skin); } } /** *用於將非Substance 外觀的界面該為Substance外觀。 * @param skin */ private void changSkin(SubstanceSkin skin) { savedBounds = getBounds(); dispose(); config = new SkinChangeDemo(true); config.getRootPane().setWindowDecorationStyle(JRootPane.FRAME); //這句是關鍵代碼,自己看API體會吧 config.setBounds(savedBounds); //保持變換皮膚時位置不變 SubstanceLookAndFeel.setSkin(skin); config.setVisible(true); config.getRootPane().updateUI(); SwingUtilities.updateComponentTreeUI(this); }
main方法:
public static void main(String args[]) { JFrame.setDefaultLookAndFeelDecorated(true); JDialog.setDefaultLookAndFeelDecorated(true); try { //新建一個圖片水印,路徑可以自己該,使用自己喜歡的圖片來做應用程序的水印圖片、 SubstanceImageWatermark watermark = new SubstanceImageWatermark(SkinChangeDemo.class.getResourceAsStream("/demo/031be.jpg")); watermark.setKind(ImageWatermarkKind.APP_CENTER); watermark.setOpacity((float) 0.7); UIManager.setLookAndFeel(new SubstanceOfficeBlue2007LookAndFeel()); SubstanceSkin skin = new OfficeBlue2007Skin().withWatermark(watermark); SubstanceLookAndFeel.setSkin(skin); } catch (UnsupportedLookAndFeelException ex) { Logger.getLogger(SkinChangeDemo.class.getName()).log(Level.SEVERE, null, ex); } java.awt.EventQueue.invokeLater(new Runnable() { public void run() { config = new SkinChangeDemo(); config.setVisible(true); config.setLocationRelativeTo(null); } }); }
點擊不同的按鈕呈現不同的外觀,JDK裡的和開源的外觀之間切換。
沒水印的效果圖: