Swing 本地外觀與Substance外觀之間的切換問題及解決方案
Posted on 2009-06-09 21:59 guanminglin@gmail.com 閱讀(32762) 評論(3) 編輯 收藏 所屬分類: JavaSE Swing應(yīng)用程序如果是在開源的Look&&Feel 之間切換,感覺很容易,但是如果
把應(yīng)用程序在開源外觀下切換到系統(tǒng)默認(rèn)的或者JDK自帶的外觀時(shí),問題就來了。
不是沒有標(biāo)題欄,就是標(biāo)題欄的外觀沒有改變,用的是系統(tǒng)的窗口裝飾。這些是因?yàn)樵趹?yīng)用程序啟動時(shí)在main方法里添加了這樣一句代碼造成的:
main方法:
點(diǎn)擊不同的按鈕呈現(xiàn)不同的外觀,JDK里的和開源的外觀之間切換。

沒水印的效果圖:



JFrame.setDefaultLookAndFeelDecorated(true);
目前解決這個(gè)問題的辦法就是先將 原來的JFrame dispose掉 ,然后在new一個(gè) JFrame ,讓原來的frame 指向這個(gè)新的JFrame。不多說,看代碼比較直觀, 核心代碼如下:
初始化應(yīng)用,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 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); //這句是關(guān)鍵代碼,自己看API體會吧
config.setBounds(savedBounds); //保持變換皮膚時(shí)位置不變
SubstanceLookAndFeel.setSkin(skin);
config.setVisible(true);
config.getRootPane().updateUI();
SwingUtilities.updateComponentTreeUI(this);
}
// 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); //這句是關(guān)鍵代碼,自己看API體會吧
config.setBounds(savedBounds); //保持變換皮膚時(shí)位置不變
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 {
//新建一個(gè)圖片水印,路徑可以自己該,使用自己喜歡的圖片來做應(yīng)用程序的水印圖片、
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);
}
});
}
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
try {
//新建一個(gè)圖片水印,路徑可以自己該,使用自己喜歡的圖片來做應(yīng)用程序的水印圖片、
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);
}
});
}
點(diǎn)擊不同的按鈕呈現(xiàn)不同的外觀,JDK里的和開源的外觀之間切換。
沒水印的效果圖:
BTW: 這篇文章里的內(nèi)容,正好可以回答http://www.javaeye.com/topic/400574?page=1 這個(gè)帖子中樓主的問題。
如果有大家有什么更好的 方法,請大家不吝賜教!
源代碼以上傳,有需要的自己下載:Demo3