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


          常用鏈接

          留言簿(4)

          隨筆檔案

          相冊

          我的兄弟們

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

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


          和代碼:
          /**
           * @(#)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;
                      
          // 計算五個頂點
                      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);
              }
          }

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

          圖示:


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

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

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

          frame.setUndecorated(true);

          怎么增加frame的拖動和可變大小?

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

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

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

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 齐齐哈尔市| 博客| 翼城县| 焉耆| 石屏县| 扎鲁特旗| 无棣县| 唐河县| 星座| 郯城县| 安岳县| 天峻县| 泉州市| 青浦区| 东海县| 玉山县| 临漳县| 马尔康县| 香格里拉县| 宁陕县| 丹江口市| 永州市| 颍上县| 福海县| 仁化县| 榆社县| 通榆县| 嘉定区| 邢台市| 禹城市| 江达县| 蒲城县| 韩城市| 湖北省| 紫阳县| 平塘县| 扎囊县| 崇左市| 衡阳县| 汕头市| 闽清县|