隨筆 - 18  文章 - 96  trackbacks - 0
          <2007年9月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          30123456


          常用鏈接

          留言簿(4)

          隨筆檔案

          相冊(cè)

          我的兄弟們

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          嗯,BeanSoft的話很有道理,令我敬佩,也許是昨天在下對(duì)那個(gè)“更好的”三個(gè)字感到一時(shí)憤慨,所以看到UI就自己擴(kuò)大了問(wèn)題,想到迎合LookAndFeel上面去了,在此說(shuō)句對(duì)不起了。你的回帖里面偏重于從整個(gè)組件的設(shè)計(jì)和重用性上,我的文章主要講的是如何將2D繪制和組件的繪制結(jié)合起來(lái),看客如果既了解了如何繪制自己想要的組件,又能設(shè)計(jì)得體,重用性高的話也算是對(duì)我拋磚引玉的欣慰了。
          多話不說(shuō),接著昨天的,現(xiàn)在我們來(lái)試想一下做一個(gè)MP3的播放軟件上的幾個(gè)播放按鈕,“上一首”是左邊有圓頂角而右邊沒(méi)有的方形按鈕,“下一首”是右邊有圓頂角而左邊沒(méi)有的方形按鈕,而播放和暫停是一個(gè)圓形的按鈕,再放上一個(gè)五角星的按鈕來(lái)評(píng)分,現(xiàn)在我們來(lái)繪制他們(當(dāng)然我們還有一個(gè)解決方案為每個(gè)Button換成圖片,每個(gè)Button得有三張:普通狀態(tài),劃過(guò),按下,不過(guò)這不是重點(diǎn))。還是先放上圖片:


          和代碼:
          /**
           * @(#)RJButton.java  0.1.0  2007-9-11
           
          */
          package ruislan.rswing;

          import java.awt.AlphaComposite;
          import java.awt.Color;
          import java.awt.Dimension;
          import java.awt.Font;
          import java.awt.GradientPaint;
          import java.awt.Graphics;
          import java.awt.Graphics2D;
          import java.awt.Point;
          import java.awt.RenderingHints;
          import java.awt.Shape;
          import java.awt.event.MouseAdapter;
          import java.awt.event.MouseEvent;
          import java.awt.geom.Arc2D;
          import java.awt.geom.GeneralPath;
          import java.awt.geom.RoundRectangle2D;

          import javax.swing.JButton;

          /**
           * Custom JButton
           * 
           * 
          @version 0.1.0
           * 
          @author ruislan <a href="mailto:z17520@126.com"/>
           
          */
          public class RButton extends JButton {
              
          private static final long serialVersionUID = 39082560987930759L;
              
          public static final Color BUTTON_COLOR1 = new Color(205255205);
              
          public static final Color BUTTON_COLOR2 = new Color(5115447);
              
          // public static final Color BUTTON_COLOR1 = new Color(125, 161, 237);
              
          // public static final Color BUTTON_COLOR2 = new Color(91, 118, 173);
              public static final Color BUTTON_FOREGROUND_COLOR = Color.WHITE;
              
          private boolean hover;
              
          private int style;
              
          public static final int ROUND_RECT = 0;
              
          public static final int LEFT_ROUND_RECT = 1;
              
          public static final int RIGHT_ROUND_RECT = 2;
              
          public static final int BALL = 3;
              
          public static final int STAR = 4;

              
          public RButton() {
                  
          this(ROUND_RECT);
              }

              
          public RButton(int style) {
                  
          this.style = style;
                  
          if (BALL == style) {
                      setPreferredSize(
          new Dimension(4242));
                  } 
          else if (STAR == style) {
                      setPreferredSize(
          new Dimension(4242));
                  }
                  setFont(
          new Font("system", Font.PLAIN, 12));
                  setBorderPainted(
          false);
                  setForeground(BUTTON_COLOR2);
                  setFocusPainted(
          false);
                  setContentAreaFilled(
          false);
                  addMouseListener(
          new MouseAdapter() {
                      @Override
                      
          public void mouseEntered(MouseEvent e) {
                          setForeground(BUTTON_FOREGROUND_COLOR);
                          hover 
          = true;
                          repaint();
                      }

                      @Override
                      
          public void mouseExited(MouseEvent e) {
                          setForeground(BUTTON_COLOR2);
                          hover 
          = false;
                          repaint();
                      }
                  });
              }

              @Override
              
          protected void paintComponent(Graphics g) {
                  Graphics2D g2d 
          = (Graphics2D) g.create();
                  
          int h = getHeight();
                  
          int w = getWidth();
                  
          float tran = 1F;
                  
          if (!hover) {
                      tran 
          = 0.3F;
                  }

                  g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                          RenderingHints.VALUE_ANTIALIAS_ON);
                  GradientPaint p1;
                  GradientPaint p2;
                  
          if (getModel().isPressed()) {
                      p1 
          = new GradientPaint(00new Color(000), 0, h - 1,
                              
          new Color(100100100));
                      p2 
          = new GradientPaint(01new Color(00050), 0, h - 3,
                              
          new Color(255255255100));
                  } 
          else {
                      p1 
          = new GradientPaint(00new Color(100100100), 0, h - 1,
                              
          new Color(000));
                      p2 
          = new GradientPaint(01new Color(255255255100), 0,
                              h 
          - 3new Color(00050));
                  }
                  g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                          tran));
                  GradientPaint gp 
          = new GradientPaint(0.0F0.0F, BUTTON_COLOR1, 0.0F,
                          h, BUTTON_COLOR2, 
          true);
                  g2d.setPaint(gp);
                  
          switch (style) {
                  
          case ROUND_RECT: {
                      RoundRectangle2D.Float r2d 
          = new RoundRectangle2D.Float(00,
                              w 
          - 1, h - 12020);
                      Shape clip 
          = g2d.getClip();
                      g2d.clip(r2d);
                      g2d.fillRect(
          00, w, h);
                      g2d.setClip(clip);
                      g2d.setPaint(p1);
                      g2d.drawRoundRect(
          00, w - 1, h - 12020);
                      g2d.setPaint(p2);
                      g2d.drawRoundRect(
          11, w - 3, h - 31818);
                      
          break;
                  }
                  
          case LEFT_ROUND_RECT: {
                      RoundRectangle2D.Float r2d 
          = new RoundRectangle2D.Float(00,
                              (w 
          - 1+ 20, h - 12020);
                      Shape clip 
          = g2d.getClip();
                      g2d.clip(r2d);
                      g2d.fillRect(
          00, w, h);
                      g2d.setClip(clip);
                      g2d.setPaint(p1);
                      g2d.drawRoundRect(
          00, (w - 1+ 20, h - 12020);
                      g2d.setPaint(p2);
                      g2d.drawRoundRect(
          11, (w - 3+ 20, h - 31818);
                      g2d.setPaint(p1);
                      g2d.drawLine(w 
          - 11, w - 1, h);
                      g2d.setPaint(p2);
                      g2d.drawLine(w 
          - 22, w - 2, h - 1);
                      
          break;
                  }
                  
          case RIGHT_ROUND_RECT: {
                      RoundRectangle2D.Float r2d 
          = new RoundRectangle2D.Float(-200,
                              (w 
          - 1+ 20, h - 12020);
                      Shape clip 
          = g2d.getClip();
                      g2d.clip(r2d);
                      g2d.fillRect(
          00, w, h);
                      g2d.setClip(clip);
                      g2d.setPaint(p1);
                      g2d.drawRoundRect(
          -200, (w - 1+ 20, h - 12020);
                      g2d.setPaint(p2);
                      g2d.drawRoundRect(
          -191, (w - 3+ 20, h - 31818);
                      g2d.setPaint(p1);
                      g2d.drawLine(
          010, h);
                      g2d.setPaint(p2);
                      g2d.drawLine(
          121, h - 1);
                      
          break;
                  }
                  
          case BALL: {
                      Arc2D.Float a2d 
          = new Arc2D.Float(00, w, h, 0360, Arc2D.CHORD);
                      Shape clip 
          = g2d.getClip();
                      g2d.clip(a2d);
                      g2d.fillRect(
          00, w, h);
                      g2d.setClip(clip);
                      g2d.setPaint(p1);
                      g2d.drawOval(
          00, w - 1, h - 1);
                      g2d.setPaint(p2);
                      g2d.drawOval(
          11, w - 3, h - 3);
                      
          break;
                  }
                  
          case STAR: {
                      
          int x = w / 2;
                      
          int y = h / 2;
                      
          int r = w / 2;
                      
          // 計(jì)算五個(gè)頂點(diǎn)
                      Point[] ps = new Point[5];
                      
          for (int i = 0; i <= 4; i++) {
                          ps[i] 
          = new Point((int) (x - r
                                  
          * Math.sin((i * 72 + 36* 2 * Math.PI / 360)),
                                  (
          int) (y + r
                                          
          * Math.cos((i * 72 + 36* 2 * Math.PI / 360)));
                      }
                      GeneralPath star 
          = new GeneralPath();
                      star.moveTo(ps[
          3].x, ps[3].y);
                      star.lineTo(ps[
          0].x, ps[0].y);
                      star.lineTo(ps[
          2].x, ps[2].y);
                      star.lineTo(ps[
          4].x, ps[4].y);
                      star.lineTo(ps[
          1].x, ps[1].y);
                      star.lineTo(ps[
          3].x, ps[3].y);
                      star.closePath();
                      Shape clip 
          = g2d.getClip();
                      g2d.clip(star);
                      g2d.fillRect(
          00, w, h);
                      g2d.setClip(clip);
                      g2d.setPaint(p1);
                      g2d.draw(star);
                      g2d.setPaint(p2);
                      g2d.draw(star);
                      
          break;
                  }
                  
          default:
                      
          break;
                  }
                  g2d.dispose();
                  
          super.paintComponent(g);
              }
          }

          這個(gè)代碼的其他地方我就不多說(shuō)了,今天主要是講一下如何來(lái)clip內(nèi)容,從而弄出我們想要的按鈕形狀(當(dāng)然其他組件也可以)
          如圖所示,假設(shè)我們的按鈕是黑色的框,我們想要的是紅色的框,那么我們首先繪出我們想要的Shape,然后得到這個(gè)按鈕的Shape,然后進(jìn)行合并剪裁,也就是說(shuō)將兩個(gè)Shape合起來(lái),然后交集部分留下,其余的去除,這樣就得到了我們所想要的圖形(五角星那個(gè)圖我們對(duì)五角星進(jìn)行了封閉closePath)。

          圖示:


          我們還可以通過(guò)幾個(gè)Area進(jìn)行合并圖形,反剪等等操作來(lái)勾勒我們想要的圖形,從而勾畫組件的圖形,如果你有閑情逸致的話,也有美感和足夠的素材的話可以寫一個(gè)StarCraft或者War3屏幕下角的操作區(qū)喲。

          posted on 2007-09-12 13:36 ruislan 閱讀(2442) 評(píng)論(11)  編輯  收藏

          FeedBack:
          # re: JButton大改造之二 - 五芒星之輝 2007-09-12 13:40 darkhe
          再頂。  回復(fù)  更多評(píng)論
            
          # re: JButton大改造之二 - 五芒星之輝 2007-09-12 15:20 交口稱贊
          不錯(cuò),還能寫出空心按鈕。  回復(fù)  更多評(píng)論
            
          # re: JButton大改造之二 - 五芒星之輝 2007-09-12 16:56 wqq
          版主:
          把測(cè)試代碼放出來(lái)吧。謝謝。  回復(fù)  更多評(píng)論
            
          # re: JButton大改造之二 - 五芒星之輝 2007-09-12 19:35 千里冰封
          太牛了,樓主,以后我會(huì)經(jīng)常光顧你的blog
          你SWING研究的不錯(cuò)哦  回復(fù)  更多評(píng)論
            
          # re: JButton大改造之二 - 五芒星之輝 2007-09-13 08:46 zht
          現(xiàn)在做Swing的很少了,贊一個(gè)
          順便問(wèn)一下,工作就是做這個(gè)?  回復(fù)  更多評(píng)論
            
          # re: JButton大改造之二 - 五芒星之輝 2007-09-13 09:30 ruislan
          NO、NO、NO,我的工作是JavaEE,天天都伺候著Spring、Hibernate、SpringMVC、DWR……  回復(fù)  更多評(píng)論
            
          # re: JButton大改造之二 - 五芒星之輝 2007-09-13 09:34 zht
          @ruislan
          呵呵,我現(xiàn)在天天做,感覺(jué)越做選擇面越窄。。。  回復(fù)  更多評(píng)論
            
          # re: JButton大改造之二 - 五芒星之輝 2007-09-13 10:00 ruislan
          一般人天天都做了一個(gè)東西,即便是再喜歡久而久之也會(huì)產(chǎn)生審美疲勞,唉。
          例如Hibernate吧,第一次接觸它就喜歡上了ORM,那個(gè)時(shí)候還在上大學(xué),然后天天就搗鼓這個(gè),課也不上,興致高昂得連什么hbm文件,事務(wù)之類都是親歷親為,但是自從工作就是跟它打交道的不久之后,就開始用生成工具來(lái)生成hbm,然后不久之后開始用AppFuse了,就連hibernate那幾個(gè)CRUD操作長(zhǎng)什么樣都不知道了。  回復(fù)  更多評(píng)論
            
          # re: JButton大改造之二 - 五芒星之輝 2007-10-22 16:41 Eastsun
          看了下樓主改造的JButton,效果確實(shí)不錯(cuò).
          不過(guò)還有個(gè)小小的缺陷:button顯示的形狀雖然變了,但其接受鼠標(biāo)事件的范圍還是原來(lái)那個(gè)矩形框.
          譬如那個(gè)五角星button,理想的效果應(yīng)該是鼠標(biāo)放到五角星里面,button才會(huì)做出各種反應(yīng),但樓主的卻不是這樣.
          解決方法也很簡(jiǎn)單,復(fù)寫父類的boolean contains(int x,int y)方法,在應(yīng)該起效果的地方返回ture就可以了.  回復(fù)  更多評(píng)論
            
          # re: JButton大改造之二 - 五芒星之輝 2008-01-19 17:07 hanjs
          問(wèn)個(gè)問(wèn)題

          frame.setUndecorated(true);

          怎么增加frame的拖動(dòng)和可變大???

          我想實(shí)現(xiàn)千千靜聽那樣的3個(gè)窗口合在一起的  回復(fù)  更多評(píng)論
            
          # re: JButton大改造之二 - 五芒星之輝 2008-01-27 17:00 hanjs
          按鈕改完可以改變形狀?

          可改panel后,還需要怎么處理frame才能支持呢?

          我現(xiàn)在是改變panel的形狀后,如使用圓角矩形后(加到frame后),可是上面的兩個(gè)角顯示不了,下面的角可以顯示,但是圓角外默認(rèn)是白色,不能實(shí)現(xiàn)理想的形狀!  回復(fù)  更多評(píng)論
            

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 葫芦岛市| 旺苍县| 彭阳县| 河西区| 凤山市| 息烽县| 视频| 金溪县| 华阴市| 余姚市| 栾川县| 田林县| 雷州市| 炎陵县| 沁源县| 景东| 辽中县| 扶余县| 阳曲县| 伊宁市| 灵璧县| 栾城县| 巴里| 永仁县| 连平县| 黎城县| 双流县| 肇源县| 阆中市| 休宁县| 富顺县| 榆中县| 尚志市| 八宿县| 景东| 巩留县| 准格尔旗| 万宁市| 神农架林区| 万山特区| 邢台县|