设置半透明的JMenuBar(2008.7.20);

源作:陈思羽.
更新:龚德伟.   2008.07.20

效果图



更新的内容:
优化了paint方法,不需要每次都创建一个BufferedImage.

修正了鼠标开时时菜单项背景不会变成半透明的问题
支持菜单普通情况下和鼠标选中时两种半透明设定


修正鼠标选中菜单时,文字变成不透明
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;

import javax.swing.ButtonModel;
import javax.swing.JComponent;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicMenuItemUI;

/**
 * 一个支持半透明的菜单UI
 * 
 * 
@author 陈思羽,龚德伟
 * @history 2008-7-20
 * 
@see <a href="http://www.blogjava.net/chensiyu04/articles/201425.html">
 *      在试牛刀(设置半透明的JMenuBar)</a>
 
*/

public class CustomMenuItemUI extends BasicMenuItemUI {
    
public static ComponentUI createUI(JComponent c) {
        
return new CustomMenuItemUI();
    }


    
/** 菜单的透明度 */
    
private static float alpha = 0.5f;
    
private static float selectionAlpha = 0.8f;

    
public static float getAlpha() {
        
return alpha;
    }


    
public static void setAlpha(float _alpha) {
        alpha 
= _alpha;
    }


    @Override
    
public void installUI(JComponent c) {
        
super.installUI(c);
        
//设为透明,这样才会更新菜单低下的内容(这个请了解Opaque的作用)
        menuItem.setOpaque(false);
    }


    
public void paint(Graphics g, JComponent comp) {
        
//创建一个graphics的副本
        Graphics2D gx = (Graphics2D) g.create();
        
//alpha 就是透明度.值越小 透明度越大
        gx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
        
//将控件画到半透明 的画布上
        super.paint(gx, comp);
        
//graphics使用后要销毁,这是良好习惯
        gx.dispose();
    }


    
/*
     * 重写了背景的绘制方法,不管Opaque的属性,只按不透明方式画菜单背景
     
*/

    @Override
    
protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) {
        ButtonModel model 
= menuItem.getModel();
        Color oldColor 
= g.getColor();
        
int menuWidth = menuItem.getWidth();
        
int menuHeight = menuItem.getHeight();
        
if (model.isArmed() || (menuItem instanceof JMenu && model.isSelected())) {
            Graphics2D g2 
= (Graphics2D) g.create(); 
            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, selectionAlpha));
            g2.setColor(bgColor);
            g2.fillRect(
00, menuWidth, menuHeight);
        }
 else {
            g.setColor(menuItem.getBackground());
            g.fillRect(
00, menuWidth, menuHeight);
        }

        g.setColor(oldColor);
    }


    @Override
    
protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, String text) {
        ButtonModel model 
= menuItem.getModel();
        
//鼠标移动菜单时文字不透明
        if (model.isArmed() || model.isSelected()) {
            Graphics2D g2 
= (Graphics2D) g.create();
            g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 
1.0f));
            
super.paintText(g2, menuItem, textRect, text);
            g2.dispose();
        }
 else {
            
super.paintText(g, menuItem, textRect, text);
        }

    }


    
/**
     * 设置选中时是否透明
     * 
@param b
     
*/

    
public static void setSelectionAlpha(float alpha) {
        selectionAlpha  
= alpha;
    }

}



import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.Popup;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicPopupMenuUI;

public class CustomPopupMenuUI extends BasicPopupMenuUI 
  
public static ComponentUI createUI(JComponent c) 
   
return new CustomPopupMenuUI(); 
  }
 
  
public void installUI(JComponent c) 
   
super.installUI(c); 
   popupMenu.setOpaque(
false); 
  }
 
  
public Popup getPopup(JPopupMenu popup, int x, int y) 
   Popup pp 
= super.getPopup(popup,x,y); 
   JPanel panel 
= (JPanel)popup.getParent(); 
   panel.setOpaque(
false); 
   
return pp; 
  }
 
}
 


import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * 半透明的菜单测试类
 * 
 * 
@author 陈思羽,龚德伟
 * @history 2008-7-20
 * 
@see <a href="http://www.blogjava.net/chensiyu04/articles/201425.html"> * 在试牛刀(设置半透明的JMenuBar)<
 *      /a>
 
*/

public class MenuTest {
    
public static void main(String[] args) throws Exception {
        
//这样把JFrame上所有JMenuBar的外观全设置为上面两个类已经写好的,这两句必须放在JMenuBar的前面 
        
//具体放在哪个方法里随便你 
        UIManager.put("PopupMenuUI""CustomPopupMenuUI");//自己看API, 
        UIManager.put("MenuItemUI""CustomMenuItemUI");
        JFrame frame 
= new JFrame();
        JMenuBar mb 
= new JMenuBar();
        frame.setJMenuBar(mb);
        JMenu menu 
= new JMenu("File");
        mb.add(menu);
        menu.add(
new JMenuItem("Open"));
        menu.add(
new JMenuItem("Save"));
        menu.add(
new JMenuItem("Close"));
        menu.add(
new JMenuItem("Exit"));
        menu 
= new JMenu("Edit");
        mb.add(menu);

//如果你把UIManager.put("PopupMenuUI","CustomPopupMenuUI"); 
//   UIManager.put("MenuItemUI","CustomMenuItemUI");   
// 这两句在上面删掉 把他们放在这里 那么只有从这往下的JMenuITem可以为透明 以上的则无效果   
        menu.add(new JMenuItem("Cut"));
        menu.add(
new JMenuItem("Copy"));
        menu.add(
new JMenuItem("Paste"));
        menu.add(
new JMenuItem("Paste Special.."));
        JPanel contentPane 
= new JPanel();
        BoxLayout layout 
= new BoxLayout(contentPane, BoxLayout.Y_AXIS);
        contentPane.setLayout(layout);
        contentPane.add(Box.createVerticalGlue());
        JSlider alphaSlider 
= new JSlider(JSlider.HORIZONTAL);
        contentPane.add(
new JLabel("菜单背景不透明度:"));
        contentPane.add(alphaSlider);
        alphaSlider.addChangeListener(
new ChangeListener() {
            
public void stateChanged(ChangeEvent e) {
                JSlider slider 
= (JSlider) e.getSource();
                
float alpha = (1.0f * slider.getValue() / 100);
                CustomMenuItemUI.setAlpha(alpha);
                slider.setToolTipText(
"不透明:" + slider.getValue());
            }

        }
);
        contentPane.add(
new JSeparator(JSeparator.HORIZONTAL));
        JSlider selectionAlphaSlider 
= new JSlider(JSlider.HORIZONTAL);
        contentPane.add(
new JLabel("菜单选中时背景不透明度:"));
        contentPane.add(selectionAlphaSlider);
        selectionAlphaSlider.addChangeListener(
new ChangeListener() {
            
public void stateChanged(ChangeEvent e) {
                JSlider slider 
= (JSlider) e.getSource();
                
float alpha = (1.0f * slider.getValue() / 100);
                CustomMenuItemUI.setSelectionAlpha(alpha);
                slider.setToolTipText(
"不透明:" + slider.getValue());
            }

        }
);
        contentPane.add(
new JSeparator(JSeparator.HORIZONTAL));
        contentPane.add(Box.createVerticalGlue());
        StringBuilder sbMsg 
= new StringBuilder();
        sbMsg.append(
"CustomMenuItemUI\r\n");
        sbMsg.append(
"一个支持半透明的菜单UI \r\n");
        sbMsg.append(
"\r\n");
        sbMsg.append(
"See Also:\r\n");
        sbMsg.append(
"在试牛刀(设置半透明的JMenuBar)\r\n");
        sbMsg.append(
"Author:\r\n");
        sbMsg.append(
"陈思羽,龚德伟\r\n");
        sbMsg.append(
"@history\r\n");
        sbMsg.append(
"2008-7-20");
        contentPane.add(
new JScrollPane(new JTextArea(sbMsg.toString())));
        frame.setContentPane(contentPane);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setSize(
200200);
        frame.setLocationRelativeTo(
null);
        frame.setVisible(
true);
    }

}

posted on 2008-05-19 16:36 相信 阅读(4315) 评论(12)  编辑  收藏 所属分类: Swing文章

评论

# re: 在试牛刀(设置半透明的JMenuBar); 2008-05-19 20:05 李志伟

写的还不错,值得学习,这些代码我可以用吗?  回复  更多评论   

# re: 在试牛刀(设置半透明的JMenuBar); 2008-05-19 20:13 相信

当然可以..这些你拿去自己改改吧..  回复  更多评论   

# re: 在试牛刀(设置半透明的JMenuBar); 2008-05-19 20:45 暴风不如雨

顶你来了!!  回复  更多评论   

# re: 在试牛刀(设置半透明的JMenuBar); 2008-07-20 19:54 kylixs

//精简后的代码
public class CustomMenuItemUI extends BasicMenuItemUI {
public static ComponentUI createUI(JComponent c) {
return new CustomMenuItemUI();
}
@Override
public void installUI(JComponent c) {
super.installUI(c);
menuItem.setOpaque(false);
}
public void paint(Graphics g, JComponent comp) {
//复制一个graphics
Graphics2D gx = (Graphics2D) g.create();
// do an alpha composite
//0.8f 就是透明度.值越小 透明度越大
gx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
//将控件画到半透明 的画布上
super.paint(gx, comp);
//graphics使用后要销毁,这是良好习惯
gx.dispose();
}
}  回复  更多评论   

# re: 在试牛刀(设置半透明的JMenuBar); 2008-07-20 22:20 相信

感谢kylixs的精简更新..  回复  更多评论   

# re: 设置半透明的JMenuBar(2008.7.20); 2008-08-23 14:44 我爱你的微笑

好!!!  回复  更多评论   

# re: 设置半透明的JMenuBar(2008.7.20); 2009-04-28 15:12 landy

顶你啦  回复  更多评论   

# re: 设置半透明的JMenuBar(2008.7.20); 2009-11-03 16:44 ㄚ琪

感謝!
這應該可以解UndeadJ的問題!  回复  更多评论   

# 报错了!!!!!!!!!!!!!![未登录] 2009-12-28 17:28 c

run:
UIDefaults.getUI() failed: no ComponentUI class for: javax.swing.JMenuItem[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=null,paintBorder=false,paintFocus=false,pressedIcon=,rolloverEnabled=false,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=Open]
java.lang.Error
at javax.swing.UIDefaults.getUIError(UIDefaults.java:711)
at javax.swing.MultiUIDefaults.getUIError(MultiUIDefaults.java:133)
at javax.swing.UIDefaults.getUI(UIDefaults.java:741)
at javax.swing.UIManager.getUI(UIManager.java:1016)
at javax.swing.JMenuItem.updateUI(JMenuItem.java:232)
at javax.swing.JMenuItem.init(JMenuItem.java:194)
at javax.swing.JMenuItem.<init>(JMenuItem.java:133)
at javax.swing.JMenuItem.<init>(JMenuItem.java:110)
at customtransparencemenu.example.MenuTest.main(MenuTest.java:47)
UIDefaults.getUI() failed: no ComponentUI class for: javax.swing.JPopupMenu[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,desiredLocationX=0,desiredLocationY=0,label=,lightWeightPopupEnabled=true,margin=,paintBorder=true]
java.lang.Error
at javax.swing.UIDefaults.getUIError(UIDefaults.java:711)
at javax.swing.MultiUIDefaults.getUIError(MultiUIDefaults.java:133)
at javax.swing.UIDefaults.getUI(UIDefaults.java:741)
at javax.swing.UIManager.getUI(UIManager.java:1016)
at javax.swing.JPopupMenu.updateUI(JPopupMenu.java:207)
at javax.swing.JPopupMenu.<init>(JPopupMenu.java:172)
at javax.swing.JPopupMenu.<init>(JPopupMenu.java:157)
at javax.swing.JMenu.ensurePopupMenuCreated  回复  更多评论   

# 报错了!!!!!!!!!!!!!![未登录] 2009-12-28 17:32 c

UIManager.put("MenuItemUI", "CustomMenuItemUI");

我觉得问题在这里,好像是要需要设置 开发人员默认值 不知道对不对???
如果对的话。请问在哪设置?  回复  更多评论   

# re: 设置半透明的JMenuBar(2008.7.20);[未登录] 2009-12-28 17:41 c

解决了,哈哈 前后不到五分钟,看来我还行。
这样解决的:
String popUI = CustomMenuItemUI.class.getName();
UIManager.put("MenuItemUI", popUI);


我想顺便问一下,你是怎么做的?是不是你配置了一个 swing.properties属性文件?还是怎么的?
  回复  更多评论   

# re: 设置半透明的JMenuBar(2008.7.20); 2011-03-02 16:18 zzt

为何编译出现KNOWN SOURCE  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
<2024年4月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

导航

统计

公告

不显示applet

常用链接

留言簿(16)

我参与的团队

随笔档案

文章分类

文章档案

新闻档案

相册

swingchina 专业搞Swing的网站

搜索

最新评论

阅读排行榜

评论排行榜