設置半透明的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.aygfsteel.com/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.aygfsteel.com/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 相信 閱讀(4342) 評論(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  回復  更多評論   

          <2008年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導航

          統計

          公告

          不顯示applet

          常用鏈接

          留言簿(16)

          我參與的團隊

          隨筆檔案

          文章分類

          文章檔案

          新聞檔案

          相冊

          swingchina 專業搞Swing的網站

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 平江县| 黎城县| 东城区| 宁化县| 奉新县| 荆门市| 桃园市| 乐安县| 平度市| 彰化县| 白城市| 余干县| 江城| 凌云县| 古田县| 南宁市| 榆林市| 康定县| 洛隆县| 隆回县| 松滋市| 修水县| 朝阳市| 墨脱县| 大埔区| 灵台县| 兴安县| 安吉县| 嘉峪关市| 渝中区| 大埔区| 平和县| 弥勒县| 台州市| 巴塘县| 温宿县| 嘉善县| 滨海县| 巩义市| 南投县| 景泰县|