Swing不丑系列:JComboBox

          一直都是一只菜鳥..不管別人怎么說.
          一直認為Swing不丑..所以打算這段時間寫個Swing不丑系列(獻丑了)

          |----------------------------------------------------------------------------------------|
                               版權聲明  版權所有 @chensiyu
                      引用請注明來源 
          www.aygfsteel.com/chensiyu04

                      本文由  陳思羽 于 2011年8月24號 出品..
          |----------------------------------------------------------------------------------------|
          -------------------------->>>>>>


          話說JComboBox 默認外觀確實不是太好看..在由于本人有時實在太賤.就是想要它好看...所以..這不..又折騰了..
          其實這個ComboBox  剛開始想改變外觀 只考慮到renderer 畢竟swing上所有的界面 顯示全靠renderer來控制..
          所以  著手寫ComboBoxRenderer.  總是覺的 JComboBox 似乎不太好搞定 因為它不但有顯示框 還有小鍵頭.
          還有彈出的List 還有ScrollBar..等等..  似乎不那么好搞...不過Swing是強大的 ..只要你能想到..就可以做到.


          那么我們要做幾件事.
          1: 重載JComboBox 并且設置面板透明
          2: 新建renderer 實現ListCellRenderer接口
          3: 重載BasicComboBoxUI

          1.重載JComboBox 并且設置面板透明 設置renderer 以及設置 ui
          public class IComboBox extends JComboBox{
           
           
          public IComboBox(){
            
          super();
            init();
           }

           
          public IComboBox(ComboBoxModel model){
            
          super(model);
            init();
           }

           
          public IComboBox(Object[] items){
            
          super(items);
            init();
           }

           
          public IComboBox(Vector<?> items){
            
          super(items);
            init();
           }

           
          private void init(){
            setOpaque(
          false);
            setUI(
          new IComboBoxUI());
            setRenderer(
          new IComboBoxRenderer());
            setBackground(XUtil.defaultComboBoxColor);
           }

           
          public Dimension getPreferredSize(){
            
          return super.getPreferredSize();
           }

          }


          2.新建renderer 實現ListCellRenderer接口.注意.這里的ComboBoxRenderer它是控制combobox彈出的List 并非控制JComboBox的 注意 他實現的是ListCellRenderer
          public class IComboBoxRenderer implements ListCellRenderer {
           
           
          private DefaultListCellRenderer defaultCellRenderer = new DefaultListCellRenderer();

           
          public IComboBoxRenderer() {
            
          super();
           }


           
          public Component getListCellRendererComponent(JList list, Object value,
             
          int index, boolean isSelected, boolean cellHasFocus) {

            JLabel renderer 
          = (JLabel)defaultCellRenderer.getListCellRendererComponent(
              list, value, index, isSelected, cellHasFocus);
            
          if(isSelected){
             renderer.setBackground(XUtil.defaultComboBoxBoundsColor);
             renderer.setForeground(Color.WHITE);
            }
          else{
             renderer.setBackground(Color.WHITE);
            }

            list.setSelectionBackground(XUtil.defaultComboBoxColor);
            list.setBorder(
          null);
            renderer.setFont(XUtil.defaultComboBoxFont);
            renderer.setHorizontalAlignment(JLabel.CENTER);
            
          return renderer;
           }

          }


          3重載BasicComboBoxUI .sure 這里當然要注意.因為他是JComboBox的繪制機制
          這里包括ComboBox右邊的那個箭頭的Button.(我們已經通過重寫 createArrowButton 來改變這個Button);
          至于彈出的List ,it in here, look it ..createPoput(); it create ComboPopup.(不好意思 最近在學英文 總是那么順口來那么幾句.)
          這里存在一個ScrollPane  它包含了List.并且我們重寫ScrollPane的paintBorder方法 來讓我們畫出List的Border


          public class IComboBoxUI extends BasicComboBoxUI {

           
          private JButton arrow;
           
          private boolean boundsLight = false;
           
          private static final int ARCWIDTH = 15;
           
          private static final int ARCHEIGHT = 15;

           
          public IComboBoxUI() {
            
          super();
           }


           
          protected JButton createArrowButton() {
            arrow 
          = new JButton();
            arrow.setIcon(XUtil.defaultComboBoxArrowIcon);
            arrow.setRolloverEnabled(
          true);
            arrow.setRolloverIcon(XUtil.defaultComboBoxArrowIcon_Into);
            arrow.setBorder(
          null);
            arrow.setBackground(XUtil.defaultComboBoxColor);
            arrow.setOpaque(
          false);
            arrow.setContentAreaFilled(
          false);
            
          return arrow;
           }


           
          public void paint(Graphics g, JComponent c) {
            hasFocus 
          = comboBox.hasFocus();
            Graphics2D g2 
          = (Graphics2D)g;
            
          if (!comboBox.isEditable()) {
             Rectangle r 
          = rectangleForCurrentValue();
             
          //重點:JComboBox的textfield 的繪制 并不是靠Renderer來控制 這點讓我很吃驚.
             
          //它會通過paintCurrentValueBackground來繪制背景
             
          //然后通過paintCurrentValue();去繪制JComboBox里顯示的值
             paintCurrentValueBackground(g2, r, hasFocus);
             paintCurrentValue(g2, r, hasFocus);
            }

            
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
              RenderingHints.VALUE_ANTIALIAS_ON);
            
          int width = (intthis.getPreferredSize(c).getWidth()
              
          + arrow.getWidth() - 2;
            
          int height = 0;
            
          int heightOffset = 0;
            
          if (comboBox.isPopupVisible()) {
             heightOffset 
          = 5;
             height 
          = (intthis.getPreferredSize(c).getHeight();
             arrow.setIcon(XUtil.defaultComboBoxArrowIcon_Into);
            }
           else {
             heightOffset 
          = 0;
             height 
          = (intthis.getPreferredSize(c).getHeight() - 1;
             arrow.setIcon(XUtil.defaultComboBoxArrowIcon);
            }

            
          if (comboBox.isFocusable()) {
             g2.setColor(
          new Color(150207254));
            }

            g2.drawRoundRect(
          00, width, height + heightOffset,ARCWIDTH,ARCHEIGHT);
           }


           
          public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus) {
            Font oldFont 
          = comboBox.getFont();
            comboBox.setFont(XUtil.defaultComboBoxFont);
            
            
          super.paintCurrentValue(g, bounds, hasFocus);
            comboBox.setFont(oldFont);
           }


           
          public Dimension getPreferredSize(JComponent c) {
            
          return super.getPreferredSize(c);
           }


           
          public boolean isBoundsLight() {
            
          return boundsLight;
           }


           
          public void setBoundsLight(boolean boundsLight) {
            
          this.boundsLight = boundsLight;
           }


           
          protected ComboPopup createPopup() {
            ComboPopup popup 
          = new BasicComboPopup(comboBox) {
             
          protected JScrollPane createScroller() {
              IScrollPane sp 
          = new IScrollPane(list,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
              sp.setHorizontalScrollBar(
          null);
              
          return sp;
             }

             
          //重載paintBorder方法 來畫出我們想要的邊框..
             public void paintBorder(Graphics g){
              Graphics2D g2 
          = (Graphics2D) g;
              g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
              g2.setColor(
          new Color(150207254));
              g2.drawRoundRect(
          0,-arrow.getHeight(),getWidth()-1,getHeight()+arrow.getHeight()-1,0,0);
             }

            }
          ;
            
          return popup;
           }

          }

          ok. 那么到這里 ComboBox這塊已經end 但是似乎還有個問題存在  那就是createPopup 方法里的ScrollPane的滾動條還是有點丑.
          so。.next 我們搞定 it.

          1:繼承 ScrollBar 并且 setUI();
          2:繼承 BasicScrollBarUI 我們來G出我們的效果.
          paintThumb 繪制scrollbar里拖動的小box 我們先畫個邊框 and draw two Orange line.
          paintTrack 繪制scrollbar里小box的軌跡.也就是那個啥(術語怎么說來著?拖拽滑塊?).
          注意:我們首先將Graphics設置透明后 在去畫面板 然后立刻把Graphics設置為不透明..
          這樣是為了能讓我們把軌跡左邊邊界畫出來...

          createIncreaseButton draw down arrowButton 小心 千萬不要use JButton button  = new JButton();
          should use BasicArrowButton 不然你將無法click this button 并產生你想要的效果..
          你猜的到 createDecreaseButton(); 方法是干什么的..(笨蛋 上面那個Button啦);

          public class IScrollBarUI extends BasicScrollBarUI{
           
          public IScrollBarUI(){
            
          super();
           }


           
          protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) {
            
          int width = thumbBounds.width;
            
          int height = thumbBounds.height;
            Graphics2D g2 
          = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            
            g2.translate(thumbBounds.x, thumbBounds.y);
            g2.setColor(XUtil.defaultComboBoxBoundsColor);
            g2.drawRoundRect(
          1,1,width-2, height-2,5,5);
            
            g2.setColor(Color.ORANGE);
            g2.drawLine(
          3,height/2,width-4,height/2);
            g2.drawLine(
          3,height/2+3,width-4,height/2+3);
            g2.translate(
          -thumbBounds.x, -thumbBounds.y);
           }


           
          protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) {
            g.setColor(XUtil.defaultComboBoxColor);
            
          int x = trackBounds.x;
            
          int y = trackBounds.y;
            
          int width = trackBounds.width;
            
          int height = trackBounds.height;
            Graphics2D g2 
          = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setComposite(AlphaComposite
              .getInstance(AlphaComposite.SRC_OVER, 
          0.1f));
            
            g2.fill3DRect(x, y, width, height, 
          true);
            g2.setComposite(AlphaComposite
              .getInstance(AlphaComposite.SRC_OVER, 1f));
            g2.setColor(XUtil.defaultComboBoxBoundsColor.brighter());
            g2.fill3DRect(x, y, 
          1, height+1true);
            
          if(trackHighlight == DECREASE_HIGHLIGHT) {
                paintDecreaseHighlight(g);
            }
           
            
          else if(trackHighlight == INCREASE_HIGHLIGHT)  {
                paintIncreaseHighlight(g);
            }

           }


           
          protected JButton createIncreaseButton(int orientation) {
            JButton button 
          = new BasicArrowButton(orientation){
             
          public void paint(Graphics g) {
              Graphics2D g2 
          = (Graphics2D)g;
              g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                      RenderingHints.VALUE_ANTIALIAS_ON);
              g2.setColor(XUtil.defaultComboBoxBoundsColor);
              g2.drawLine(
          0,0,0,getHeight());
              g2.drawLine(
          0,0,getWidth(),0-1);
              g2.drawImage(((ImageIcon)XUtil.defaultComboBoxArrowIcon_Into).getImage(),
          -1,0,null);
             }

            }
          ;
            button.setOpaque(
          false);
            
          return button;
           }


           
          protected JButton createDecreaseButton(int orientation) {

            
            JButton button 
          = new BasicArrowButton(orientation){
             
          public void paint(Graphics g) {
              Graphics2D g2 
          = (Graphics2D)g;
              g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                      RenderingHints.VALUE_ANTIALIAS_ON);
              g2.setColor(XUtil.defaultComboBoxBoundsColor);
              g2.drawLine(
          0,0,0,getHeight());
              g2.drawLine(
          0,getHeight()-1,getWidth(),getHeight());
              g2.drawImage(((ImageIcon)XUtil.defaultComboBoxArrowIcon_Into).getImage(),
          -1,0,null);
             }

            }
          ;
            button.setOpaque(
          false);
            
          return button;
           }

          }

          posted on 2011-03-23 16:58 相信 閱讀(7560) 評論(12)  編輯  收藏 所屬分類: Swing文章

          評論

          # re: Swing不丑系列:JComboBox 2011-03-23 20:53 greatghoul

          lz真是有堅強毅力,這樣重下來還是挺費勁的嘛。  回復  更多評論   

          # re: Swing不丑系列:JComboBox 2011-03-23 20:57 相信

          @greatghoul

          可以要任何想要的效果....其實有時候覺得 做富客戶端的 如果美工底子好的話...會更帥 哈哈 ....  回復  更多評論   

          # re: Swing不丑系列:JComboBox 2011-03-24 17:10 鄭州SEO

          確實好看多了!!!  回復  更多評論   

          # re: Swing不丑系列:JComboBox 2011-03-24 17:11 相信

          還不算最好看。。有時間繼續完美下。。(準備讓它邊框發光...)  回復  更多評論   

          # re: Swing不丑系列:JComboBox[未登錄] 2011-03-24 23:09 Charlie

          支持樓主  回復  更多評論   

          # re: Swing不丑系列:JComboBox 2011-03-27 13:09 penngo

          不錯!界面重繪用得利害。  回復  更多評論   

          # re: Swing不丑系列:JComboBox[未登錄] 2011-08-11 09:46 haha

          感謝分享 不過缺少了兩個類啊  回復  更多評論   

          # re: Swing不丑系列:JComboBox 2012-08-15 13:06 hxy

          還是放棄單純的用代碼美化Swing組件,想炫 代碼很難炫過圖片(保證性能的前提下)  回復  更多評論   

          # re: Swing不丑系列:JComboBox[未登錄] 2012-11-27 21:06 文斌

          XUtil是啥?  回復  更多評論   

          # re: Swing不丑系列:JComboBox 2013-11-03 21:13 路過

          XUtil類和IScrollPane類沒有- -搞不出來  回復  更多評論   

          # re: Swing不丑系列:JComboBox 2014-07-17 15:07 coverfate

          你好,請問能提供缺少的兩個類么,還有qq群好像加不來啊  回復  更多評論   

          # re: Swing不丑系列:JComboBox 2014-07-17 15:25 相信

          @coverfate

          群沒收到你的消息  回復  更多評論   

          <2011年3月>
          272812345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          導航

          統計

          公告

          不顯示applet

          常用鏈接

          留言簿(16)

          我參與的團隊

          隨筆檔案

          文章分類

          文章檔案

          新聞檔案

          相冊

          swingchina 專業搞Swing的網站

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 明溪县| 阿城市| 敦煌市| 天全县| 阿巴嘎旗| 宕昌县| 临猗县| 建湖县| 辽中县| 临漳县| 屏山县| 含山县| 磐安县| 图片| 洪湖市| 体育| 金昌市| 资源县| 长海县| 松滋市| 久治县| 扶余县| 永平县| 东辽县| 连州市| 宝坻区| 徐水县| 定陶县| 湘潭市| 平安县| 平凉市| 黄大仙区| 呼玛县| 丹巴县| 资阳市| 恩施市| 嘉兴市| 肃宁县| 红原县| 孟州市| 通州市|