对于图形界面来说,按钮神马的最最常用了。但是老用系统提供的那几个按钮控件不觉得单调吗?为了让界面看起来了更加炫,其实按钮控件完全可以DIY~~ 本篇就讲解怎么DIY属于自己的Button!Let’s go!!

 

1.定制自己的Button,首先就需要前景,背景和按钮按下时的样式,当然按钮的位置和宽高也是必须的。

p_w_picpath p_w_picpath 

后者就是按钮被按下的样子。仔细观察按钮,按钮是由3部分组成

前景

p_w_picpath

背景

p_w_picpath

按钮被按下时

p_w_picpath

 

由此,我们可以大致定义出Button类

   1: public class MyButton {
   2:     /**按钮的位置和宽高*/
   3:     private float posX, posY, width, height;
   4:     /**按钮的前景,背景以及被按下时的样式*/
   5:     private Image foreground, background, clicked;
   6:     
   7:     public interface ClickAction {
   8:         public void onButtonClick(MyButton button);
   9:     }
  10:  
  11:     public MyButton(float posX, float posY) {
  12:         this(posX, posY, 200, 60);
  13:     }
  14:  
  15:     public MyButton(float posX, float posY, float width, float height) {
  16:         super();
  17:         this.posX = posX;
  18:         this.posY = posY;
  19:         this.width = width;
  20:         this.height = height;
  21:         
  22:         try {
  23:             foreground = new Image("res/p_w_picpath/btn_playnow.png");
  24:             background = new Image("res/p_w_picpath/btn_normal.png");
  25:             clicked = new Image("res/p_w_picpath/btn_pressed.png");
  26:         } catch (SlickException e) {
  27:             e.printStackTrace();
  28:         }
  29:     }
  30:  
  31:     public void draw(){
  32:         background.draw(posX, posY, width, height);
  33:         foreground.draw(posX, posY, width, height);
  34:     }
  35:     
  36: }

 

然后可以在Slick框架里定义一个MyButton对象,并绘制出来。

p_w_picpath

 

2.接下来,也是最重要的。按钮的功能是什么?不就是点击按钮然后触发事件响应吗?因此,要定义按钮的事件响应。

   1: public class MyButton {
   2:     .....
   3:     
   4:     public interface ClickAction {
   5:         public void onButtonClick(MyButton button);
   6:     }
   7:  
   8:     .....
   9: }

回想在Swing编程里,为一个按钮设置监听器

   1: button.addActionListener(new ActionListener() {
   2:             
   3:             @Override
   4:             public void actionPerformed(ActionEvent e) {
   5:             }
   6:         });

可以看到这里的ActionListener不是接口就是抽象类。当点击按钮时,就会调用ActionListener.actionPerformed()方法。

同样的,在自定义按钮中,我们也可以在类的内部定义一个ClickAction接口,当自定义按钮被按下时,调用ClickAction.onButtonClick()方法。

 

因此,我们可以在onButtonClick()实现当按钮被按下时,会触发事件的代码。

 

3. 然而,怎么才能知道按钮是否被点击或者按下了呢?

在Slick框架里,会提供相应的鼠标方法,包括mousePressed,mouseReslease, mouseClicked等方法,这些方法参数中,系统会传入当前鼠标所在的位置。

因此,只要知道鼠标的位置以及鼠标的状态(按下,释放),就可以知道当前按钮是否被按下或点击。

可以在,MyButton内加入鼠标点击的方法。

   1: public class MyButton {
   2:     /**按钮的位置和宽高*/
   3:     private float posX, posY, width, height;
   4:     /**按钮的前景,背景以及被按下时的样式*/
   5:     private Image foreground, background, clicked;
   6:     private boolean isPressed, isRelease;
   7:     private ClickAction action;//持有点击响应接口的引用,当按钮被点击时,调用该接口的方法.
   8:        
   9:     public void setOnClickAction(ClickAction action){
  10:         this.action = action;
  11:     }
  12:  
  13:     public void draw(){
  14:         background.draw(posX, posY, width, height);
  15:         foreground.draw(posX, posY, width, height);
  16:     }
  17:     
  18:     public void mouseClicked(float mousex, float mousey){
  19:         //Util是一个工具类,其中的inBound方法是判断一个点是否在一个矩形当中
  20:         //posX,posY是矩形左上角的坐标,width,height是矩形的宽高
  21:         //mousex,mousey是鼠标的位置
  22:         //因此,这段代码就是判断当前鼠标位置是否在按钮范围,如果在就调用按钮响应事件
  23:         if(Util.inBound(posX, posY, width, height, mousex, mousey))
  24:             action.onButtonClick(this);
  25:     }
  26: }

然后在Slick框架内mouseClicked()内直接调用MyButton.mouseClicked()即可

   1: @Override
   2: public void mouseClicked(int button, int x, int y, int clickCount) {
   3:     this.button.mouseClicked(x, y);
   4: }

 

接着来测试一下自定义按钮

   1: button = new MyButton(100, 100);
   2: button.setOnClickAction(new MyButton.ClickAction() {
   3:     
   4:     @Override
   5:     public void onButtonClick(MyButton button) {
   6:         // TODO Auto-generated method stub
   7:         System.out.println("按钮被点击");
   8:     }
   9: });

测试结果:

p_w_picpathp_w_picpath

 

4.现在,按钮的基本功能已经实现,但还是有瑕疵….. 你能看出来按钮时被按了吗??效果都是一样的,按与不按根本没有区别。

  为了解决这一问题,就要为按钮添加状态。

   1: private BUTTON_STATE curState;
   2:  
   3: private enum BUTTON_STATE{
   4:     BUTTON_STATE_IDLE,//按钮空闲时的状态,即按钮未被按下
   5:     BUTTON_STATE_CLICKING//按钮按下时的状态
   6: };

然后就要在点击的方法里改变按钮的状态(PS点击 Click包括 按下 Pressed 和 释放 Release)

   1: public void mouseRelease(float mousex, float mousey){
   2:     if(Util.inBound(posX, posY, width, height, mousex, mousey))
   3:         curState = BUTTON_STATE.BUTTON_STATE_CLICKING.BUTTON_STATE_IDLE;
   4: }
   5:  
   6: public void mousePressed(float mousex, float mousey){
   7:     if(Util.inBound(posX, posY, width, height, mousex, mousey))
   8:         curState = BUTTON_STATE.BUTTON_STATE_CLICKING;
   9: }

 

此时,绘制按钮就要根据按钮的状态来绘制了

   1: public void draw(){
   2:     switch (curState) {
   3:     case BUTTON_STATE_IDLE:
   4:         background.draw(posX, posY, width, height);
   5:         foreground.draw(posX, posY, width, height);
   6:         break;
   7:     
   8:     case BUTTON_STATE_CLICKING:
   9:         clicked.draw(posX, posY, width, height);
  10:         foreground.draw(posX, posY, width, height);
  11:         break;
  12:     }
  13: }

 

然后在Slick框架内的mousePressed,mouseRelease调用MyButton.mousePressed,MyButton.mouseRelease,用于改变按钮的状态。

   1: @Override
   2: public void mouseReleased(int button, int x, int y) {
   3:     this.button.mouseRelease(x, y);
   4: }
   5:  
   6: @Override
   7: public void mousePressed(int button, int x, int y) {
   8:     this.button.mousePressed(x, y);
   9: }

 

最后来测试一下

p_w_picpathp_w_picpath

p_w_picpath

 

总结:自定义按钮的步骤

1. 定义按钮的前景,背景和被按下时的样式

2.定义按钮的事件响应(最重要!!!)

3.判断按钮是否被按下

4.为按钮添加状态,被根据情况改变状态。