Swing


          天行健 君子以自強不息

          posts - 69, comments - 215, trackbacks - 0, articles - 16
             :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          JavaSwing也驚艷之一:水晶之戀

          Posted on 2009-02-20 00:18 zht 閱讀(12230) 評論(24)  編輯  收藏 所屬分類: Swing
           

          一、序言

          關于“Java做不好桌面”的爭論已經由來已久。雖然SwingJava2D已經有超過十年的歷史,也有JIDEJGoodiesTWaver等不少開源Swing組件,但是用Java做桌面程序仍然不是一件輕松的事。本《Java也驚艷》系列文章,就是想通過一些簡單生動的例子,和大家一起認識Java、探索Swing。其實你只需要多一點創意、多一點耐心,你的Java程序也可以“驚艷”!本文就帶您一起進入Java的“水晶之戀”。

           

          二、立體水晶效果

          受蘋果公司的影響,現在立體水晶風格的界面非常流行。Java也可以嗎?我們不妨先嘗試一下用Java繪制一個立體水晶風格的按鈕到底有多難。一個立體的水晶按鈕應當有一個圖標、一個圓角矩形區域、邊框以及一些立體反光效果,如下圖:

           

          簡單思路如下:先畫矩形區域,然后畫圖標,然后設置clip并畫高亮反光區域,最后畫外部邊框。

          具體實現比較簡單,主要代碼如下:

          Color color = TWaverUtil.getRandomColor(); 
           RoundRectangle2D body 
          = new RoundRectangle2D.Float(x, y, size, size, size / 3, size / 3
          ); 

          //draw body 

          g2d.setColor(color); 
          GradientPaint paint 
          = new
           GradientPaint(x, 
                              y, 
                              color.darker(), 
                              x, 
                              y 
          +
           size, 
                              color.brighter().brighter()); 
          g2d.setPaint(paint); 
          g2d.fill(body); 

          //draw image 

          g2d.setClip(body); 
          Image image 
          = TWaverUtil.getImage("/glass/" + i + ".png"
          ); 
          g2d.drawImage(image, 
                         x 
          + (size - image.getWidth(null)) / 2

                         y 
          + (size - image.getHeight(null)) / 2

                         
          null
          ); 
          g2d.setClip(
          null
          ); 

          //draw highlight. 

          Shape highlightArea = createHighlightShape(x, y, size, body); 
          g2d.setColor(
          new Color(255255255150
          )); 
          g2d.fill(highlightArea); 

          //draw outline. 

          g2d.setColor(color.darkGray); 
          g2d.draw(body);

          其中,對高亮區域的計算,可以用一個圓心在左上方的大圓形和矩形進行剪切:
          private static Shape createHighlightShape(int centerX, int centerY, int size, Shape body) { 
          double myRadius = size * 4

            
          double x = centerX - size * 2.3

            
          double y = centerY - size * 3.2

            Ellipse2D.Double circle 
          = new
           Ellipse2D.Double(x, y, myRadius, myRadius); 
            Area area 
          = new
           Area(circle); 
            area.intersect(
          new
           Area(body)); 
            
          return
           area; 
          }
           

          運行程序效果如下:

           


          三、更多變化

          根據上面例子稍作形狀變換,可以畫出立體水晶球的按鈕。
          Color color = TWaverUtil.getRandomColor(); 

          Ellipse2D.Double circle 
          = new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2, radius * 2
          ); 

          //draw body 

          g2d.setColor(color); 
          GradientPaint paint 
          = new GradientPaint(centerX, centerY, color, centerX, centerY + radius * 2
          , color.brighter().brighter()); 
          g2d.setPaint(paint); 
          g2d.fill(circle); 

          //draw image 

          g2d.setClip(circle); 
          Image image 
          = TWaverUtil.getImage("/glass/" + i + ".png"
          ); 
          g2d.drawImage(image, 
          centerX 
          - image.getWidth(null/ 2

                           centerY 
          - image.getHeight(null/ 2

                           
          null
          ); 
          g2d.setClip(
          null
          ); 

          //draw highlight. 

          Shape highlightArea = createHighlightShape(centerX, centerY, radius); 
          g2d.setColor(
          new Color(255255255150
          )); 
          g2d.fill(highlightArea);

          唯一略有不同的部分是,水晶球的高亮區域要用兩個圓形拼切:

          private static Shape createHighlightShape(int centerX, int centerY, int radius) { 
          double myRadius = radius * 0.8

            
          double x = centerX -
           myRadius; 
            
          double y1 = centerY - myRadius - myRadius / 5

            
          double y2 = centerY - myRadius - myRadius / 5 * 2


            Ellipse2D.Double circle1 
          = new Ellipse2D.Double(x, y1, myRadius * 2, myRadius * 2
          ); 
            Ellipse2D.Double circle2 
          = new Ellipse2D.Double(x, y2, myRadius * 2, myRadius * 2
          ); 

            Area area 
          = new
           Area(circle1); 
            area.intersect(
          new
           Area(circle2)); 
            
          return
           area; 
          }
           

          運行效果如下:


          如果再來點兒循環、隨機大小、隨機位置、隨機顏色,就可以做出絢麗的“吹肥皂泡”的效果


           

          四、融入Swing組件

          以上例子僅使用了Java2D進行繪圖。在實際使用中,需要將這些效果應用的Swing組件中,例如按鈕等。一個簡單的方式是:將以上圖形效果在內存中生成內存圖片并封裝到一個ImageIcon中,然后將ImageIcon圖標作為JButton的圖標進行顯示。

          public static Image createImageIcon(Image phantom, int size) {
          BufferedImage bi 
          = new
           BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2d 
          =
           bi.createGraphics();
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            
          int center = size / 2
          ;
            
          int radius =
           center;

            
          //此處進行畫圖


            g2d.dispose();
            
          return bi;
          }
           

          然后,用這些Icon創建一些按鈕并顯示:

          public static void main(String[] args) throws Exception {
          JFrame frame 
          = new
           JFrame();
            frame.getContentPane().setLayout(
          new
           FlowLayout());
            frame.getContentPane().add(
          new JButton("按鈕1"new ImageIcon(createImageIcon(null60
          ))));
            frame.getContentPane().add(
          new JButton("按鈕2"new ImageIcon(createImageIcon(null60
          ))));
            frame.getContentPane().add(
          new JButton("按鈕3"new ImageIcon(createImageIcon(null60
          ))));
            frame.getContentPane().add(
          new JButton("使用Java2D創建的立體水晶風格的按鈕"new ImageIcon(createImageIcon(null30
          ))));
            frame.setSize(
          500300
          );
            frame.setTitle(
          "Java也驚艷"
          );
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            TWaverUtil.centerWindow(frame);
            frame.setVisible(
          true
          );
          }

             

          效果如下圖:

          本例子沒有使用Look And Feel。你也可以使用JGoodies來美化一下,效果肯定更好。

          五、總結

          可以看出,畫出這類立體水晶效果并不難,只需仔細觀察這些效果的光學細節,并用Java2DAPI來實現即可。這些例子稍作改進,就可以用來繪制JButtonSwing組件,并用在實際項目中。或者,也可以應用這些技巧來做一些復雜圖形界面,如在TWaver中做出的網絡拓撲圖效果:

           

          本文知識要點:

          n         漸變填充:這個使用GradientPaint就行了;

          n         使用Clip:類似蒙版/剪切的Java2D技術。看看GraphicssetClip函數就明白了;

          n         Area的使用:主要是Area的相交、合并等幾個常見圖形處理手法。詳細請看java.awt.geom.Area類;

          n         生成內存圖片:主要是BufferedImage類的使用;

          如果大家感興趣,可以嘗試用上述Java2D技巧實現下圖效果:

          以上內容轉載請注明
           

          六、參考資料

          http://java.sun.com/j2se/1.4.2/docs/guide/2d/spec/j2d-bookTOC.html

          http://java.sun.com/j2se/1.4.2/docs/guide/2d/spec.html

          http://www.apl.jhu.edu/~hall/java/Java2D-Tutorial.html

          主站蜘蛛池模板: 英山县| 万年县| 本溪市| 舒兰市| 江城| 凌海市| 肃北| 堆龙德庆县| 清徐县| 高青县| 微山县| 奉化市| 凤城市| 固原市| 焦作市| 崇礼县| 儋州市| 濮阳市| 西乌| 遵义市| 广宗县| 安国市| 梅州市| 慈溪市| 东平县| 临桂县| 华池县| 晋中市| 新田县| 陆河县| 日喀则市| 英超| 阿鲁科尔沁旗| 收藏| 永宁县| 新和县| 崇州市| 丹棱县| 枝江市| 昌乐县| 新沂市|