JButton大改造之二 - 五芒星之辉

JButton大改造之二 - 五芒星之辉
嗯,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:[email protected]"/>
 
*/
public   class  RButton  extends  JButton {
    
private   static   final   long  serialVersionUID  =   39082560987930759L ;
    
public   static   final  Color BUTTON_COLOR1  =   new  Color( 205 255 205 );
    
public   static   final  Color BUTTON_COLOR2  =   new  Color( 51 154 47 );
    
//  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( 42 42 ));
        } 
else   if  (STAR  ==  style) {
            setPreferredSize(
new  Dimension( 42 42 ));
        }
        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( 0 0 new  Color( 0 0 0 ),  0 , h  -   1 ,
                    
new  Color( 100 100 100 ));
            p2 
=   new  GradientPaint( 0 1 new  Color( 0 0 0 50 ),  0 , h  -   3 ,
                    
new  Color( 255 255 255 100 ));
        } 
else  {
            p1 
=   new  GradientPaint( 0 0 new  Color( 100 100 100 ),  0 , h  -   1 ,
                    
new  Color( 0 0 0 ));
            p2 
=   new  GradientPaint( 0 1 new  Color( 255 255 255 100 ),  0 ,
                    h 
-   3 new  Color( 0 0 0 50 ));
        }
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                tran));
        GradientPaint gp 
=   new  GradientPaint( 0.0F 0.0F , BUTTON_COLOR1,  0.0F ,
                h, BUTTON_COLOR2, 
true );
        g2d.setPaint(gp);
        
switch  (style) {
        
case  ROUND_RECT: {
            RoundRectangle2D.Float r2d 
=   new  RoundRectangle2D.Float( 0 0 ,
                    w 
-   1 , h  -   1 20 20 );
            Shape clip 
=  g2d.getClip();
            g2d.clip(r2d);
            g2d.fillRect(
0 0 , w, h);
            g2d.setClip(clip);
            g2d.setPaint(p1);
            g2d.drawRoundRect(
0 0 , w  -   1 , h  -   1 20 20 );
            g2d.setPaint(p2);
            g2d.drawRoundRect(
1 1 , w  -   3 , h  -   3 18 18 );
            
break ;
        }
        
case  LEFT_ROUND_RECT: {
            RoundRectangle2D.Float r2d 
=   new  RoundRectangle2D.Float( 0 0 ,
                    (w 
-   1 +   20 , h  -   1 20 20 );
            Shape clip 
=  g2d.getClip();
            g2d.clip(r2d);
            g2d.fillRect(
0 0 , w, h);
            g2d.setClip(clip);
            g2d.setPaint(p1);
            g2d.drawRoundRect(
0 0 , (w  -   1 +   20 , h  -   1 20 20 );
            g2d.setPaint(p2);
            g2d.drawRoundRect(
1 1 , (w  -   3 +   20 , h  -   3 18 18 );
            g2d.setPaint(p1);
            g2d.drawLine(w 
-   1 1 , w  -   1 , h);
            g2d.setPaint(p2);
            g2d.drawLine(w 
-   2 2 , w  -   2 , h  -   1 );
            
break ;
        }
        
case  RIGHT_ROUND_RECT: {
            RoundRectangle2D.Float r2d 
=   new  RoundRectangle2D.Float( - 20 0 ,
                    (w 
-   1 +   20 , h  -   1 20 20 );
            Shape clip 
=  g2d.getClip();
            g2d.clip(r2d);
            g2d.fillRect(
0 0 , w, h);
            g2d.setClip(clip);
            g2d.setPaint(p1);
            g2d.drawRoundRect(
- 20 0 , (w  -   1 +   20 , h  -   1 20 20 );
            g2d.setPaint(p2);
            g2d.drawRoundRect(
- 19 1 , (w  -   3 +   20 , h  -   3 18 18 );
            g2d.setPaint(p1);
            g2d.drawLine(
0 1 0 , h);
            g2d.setPaint(p2);
            g2d.drawLine(
1 2 1 , h  -   1 );
            
break ;
        }
        
case  BALL: {
            Arc2D.Float a2d 
=   new  Arc2D.Float( 0 0 , w, h,  0 360 , Arc2D.CHORD);
            Shape clip 
=  g2d.getClip();
            g2d.clip(a2d);
            g2d.fillRect(
0 0 , w, h);
            g2d.setClip(clip);
            g2d.setPaint(p1);
            g2d.drawOval(
0 0 , w  -   1 , h  -   1 );
            g2d.setPaint(p2);
            g2d.drawOval(
1 1 , 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(
0 0 , 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屏幕下角的操作区哟。

你可能感兴趣的:(JButton大改造之二 - 五芒星之辉)