【唠叨】

按钮类CCControlButton继承于控件类CCControl。

控件类CCControl主要向子类提供了一系列的控件触发事件。当子控件触发相关的事件后,就会执行相关的控件事件回调函数。这与之前讲的CCMenu中的菜单按钮回调是类似的。

控件类CCControl主要有三个子类:

(1)开关控件CCControlSwitch

(2)滑块控件CCControlSlider

(3)按钮控件CCControlButton

本节讲的是其子类其中之一:按钮类CCControlButton。


【致谢】

http://gl.paea.cn/contents/22933f46650c8213.html


【Demo下载】

https://github.com/shahdza/Cocos_LearningTest/tree/master/demo_%E6%8C%89%E9%92%AE%E6%8E%A7%E4%BB%B6CCControlButton


【3.x】

(1)去掉“CC”

(2)对象类CCObject改为Ref

(3)按钮事件回调依旧为cccontrol_selector,没有使用 CC_CALLBACK_2

(4)按钮状态 CCControlState 改为强枚举 Control::State

//NORMAL//正常HIGH_LIGHTED//高亮(即在内部触摸状态下)DISABLED//禁用SELECTED//选中//

(5)按钮事件CCControlEvent改为强枚举Control::EventType

//TOUCH_DOWN//刚刚开始触摸按钮时DRAG_INSIDE//在内部拖动时(保持触摸状态下)DRAG_OUTSIDE//在外部拖动时(保持触摸状态下)DRAG_ENTER//拖动刚进入内部时(保持触摸状态下)DRAG_EXIT//拖动刚离开内部时(保持触摸状态下)TOUCH_UP_INSIDE//在内部抬起手指(保持触摸状态下)TOUCH_UP_OUTSIDE//在外部抬起手指(保持触摸状态下)TOUCH_CANCEL//取消触点//


(6)其他变化不大。




【CCControlButton】

按钮控件CCControlButton,想必大家对这个再熟悉不过了吧?每个游戏基本都会用到按钮。

一个按钮不仅有几种不同的按钮状态,而且还有一些按钮事件。另外按钮控件CCControlButton使用的背景图片是点九图CCScale9Sprite,可以使得按钮在变大的情况下,尽量保持棱角不失真。


1、按钮状态CCControlState

//CCControlStateNormal//正常CCControlStateHighlighted//高亮(即在内部触摸状态下)CCControlStateDisabled//禁用CCControlStateSelected//选中//


2、按钮事件CCControlEvent

//CCControlEventTouchDown//刚刚开始触摸按钮时CCControlEventTouchDragInside//在内部拖动时(保持触摸状态下)CCControlEventTouchDragOutside//在外部拖动时(保持触摸状态下)CCControlEventTouchDragEnter//拖动刚进入内部时(保持触摸状态下)CCControlEventTouchDragExit//拖动刚离开内部时(保持触摸状态下)CCControlEventTouchUpInside//在内部抬起手指(保持触摸状态下)CCControlEventTouchUpOutside//在外部抬起手指(保持触摸状态下)CCControlEventTouchCancel//取消触点//


3、绑定按钮事件的方法

////绑定控件事件addTargetWithActionForControlEvents(this,cccontrol_selector(HelloWorld::touchDownAction),CCControlEventTouchDown);voidaddTargetWithActionForControlEvents(CCObject*target,SEL_CCControlHandleraction,CCControlEventcontrolEvents);//删除控件事件//removeTargetWithActionForControlEvents(this,cccontrol_selector(HelloWorld::touchDownAction),CCControlEventTouchDown);voidremoveTargetWithActionForControlEvents(CCObject*target,SEL_CCControlHandleraction,CCControlEventcontrolEvents);//


4、需要引用的头文件及命名空间

//#include"cocos-ext.h"//包含cocos-ext.h头文件usingnamespacecocos2d::extension;//引用cocos2d::extension命名空间//


5、常用操作如下

//classCCControlButton:publicCCControl{/***创建CCControlButton的三种方法*///使用点九图CCScale9Sprite,按钮中不带标签CCLabelstaticCCControlButton*create(CCScale9Sprite*sprite);//使用标签label,可以是CCLabelTTF、CCLabelBMFontstaticCCControlButton*create(CCNode*label,CCScale9Sprite*backgroundSprite);//title:标签内容//fontName:字体资源,如"Arial"//fontSize:字体大小,默认12//内部创建的标签为CCLabelTTFstaticCCControlButton*create(std::stringtitle,constchar*fontName,floatfontSize);/***属性设置1(在当前CCControlState下)*getCurrentTitle,getCurrentTitleColor,*TitleLabel,BackgroundSprite,PreferredSize*///当前显示的标签内容,只读getCurrentTitleCC_SYNTHESIZE_READONLY(CCString*,m_currentTitle,CurrentTitle);//当前显示的标签内容颜色,只读getCurrentTitleColorCC_SYNTHESIZE_READONLY_PASS_BY_REF(ccColor3B,m_currentTitleColor,CurrentTitleColor);//设置当前CCControlState下的标签,set/getCC_SYNTHESIZE_RETAIN(CCNode*,m_titleLabel,TitleLabel);//设置当前CCControlState下的背景精灵,set/getCC_SYNTHESIZE_RETAIN(CCScale9Sprite*,m_backgroundSprite,BackgroundSprite);//设置按钮大小,若标签label大小大于按钮,将自动扩展,set/get。//不过经过我的测试:设置了,反而按钮大小被固定了。没有按照label的大小进行自动伸展了。CC_PROPERTY(CCSize,m_preferredSize,PreferredSize);/***属性设置2(在指定CCControlState下)*setTitleLabelForState,setTitleForState,setTitleColorForState,*setTitleTTFForState,setTitleTTFSizeForState,*setTitleBMFontForState,*setBackgroundSpriteForState,setBackgroundSpriteFrameForState,getBackgroundSpriteForState*///设置在指定CCControlState下的字体标签//若未设置标签,默认为CCButtonStateNormal状态的字体标签//字体标签可以是CCLabelTTF、CCLabelBMFontvirtualvoidsetTitleLabelForState(CCNode*label,CCControlStatestate);virtualCCNode*getTitleLabelForState(CCControlStatestate);//设置在指定CCControlState下的标签内容//若未设置标签,默认返回CCButtonStateNormal状态的标签内容virtualvoidsetTitleForState(CCString*title,CCControlStatestate);virtualCCString*getTitleForState(CCControlStatestate);//设置在指定CCControlState下的标签颜色virtualvoidsetTitleColorForState(ccColor3Bcolor,CCControlStatestate);virtualconstccColor3BgetTitleColorForState(CCControlStatestate);//###############################################################################//设置在指定CCControlState下的标签为CCLabelTTF//fntFile为字体资源名,如"Arial"virtualvoidsetTitleTTFForState(constchar*fntFile,CCControlStatestate);virtualconstchar*getTitleTTFForState(CCControlStatestate);//设置在指定CCControlState下的CCLabelTTF标签的字体大小virtualvoidsetTitleTTFSizeForState(floatsize,CCControlStatestate);virtualfloatgetTitleTTFSizeForState(CCControlStatestate);//###############################################################################//设置在指定CCControlState下的标签为CCLabelBMFont//fntFile为字体资源名,如*.fntvirtualvoidsetTitleBMFontForState(constchar*fntFile,CCControlStatestate);virtualconstchar*getTitleBMFontForState(CCControlStatestate);//###############################################################################//使用点九图CCScale9Sprite,设置在指定CCControlState下的背景精灵virtualvoidsetBackgroundSpriteForState(CCScale9Sprite*sprite,CCControlStatestate);//使用精灵帧CCSpriteFrame,设置在指定CCControlState下的背景精灵//其实在内部实现的代码,实际上是利用精灵帧spriteFrame创建了点九图CCScale9Sprite作为背景精灵virtualvoidsetBackgroundSpriteFrameForState(CCSpriteFrame*spriteFrame,CCControlStatestate);//获取在指定CCControlState下的背景图virtualCCScale9Sprite*getBackgroundSpriteForState(CCControlStatestate);/***继承于父类*/virtualvoidsetEnabled(boolenabled);//是否启用virtualvoidsetSelected(boolenabled);//是否选中virtualvoidsetHighlighted(boolenabled);//是否高亮};//




【代码实战】

代码来源于cocos2dx的官方项目TestCpp中。



1、按钮背景(正常、高亮)


2、引入头文件和命名空间

//#include"cocos-ext.h"usingnamespacecocos2d::extension;//


3、在HelloWorld.h中声明按钮事件的回调函数、显示按钮状态的Label

//CCLabelTTF*displayLabel;//显示按钮状态的labelvoidtouchDownAction(CCObject*sender,CCControlEventcontrolEvent);//刚刚开始触摸按钮时voidtouchDragInsideAction(CCObject*sender,CCControlEventcontrolEvent);//在内部拖动时(保持触摸状态下)voidtouchDragOutsideAction(CCObject*sender,CCControlEventcontrolEvent);//在外部拖动时(保持触摸状态下)voidtouchDragEnterAction(CCObject*sender,CCControlEventcontrolEvent);//拖动刚进入内部时(保持触摸状态下)voidtouchDragExitAction(CCObject*sender,CCControlEventcontrolEvent);//拖动刚离开内部时(保持触摸状态下)voidtouchUpInsideAction(CCObject*sender,CCControlEventcontrolEvent);//在内部抬起手指(保持触摸状态下)voidtouchUpOutsideAction(CCObject*sender,CCControlEventcontrolEvent);//在外部抬起手指(保持触摸状态下)voidtouchCancelAction(CCObject*sender,CCControlEventcontrolEvent);//取消触点//


4、在HelloWorld.cpp的init中创建按钮,并绑定按钮事件

//boolHelloWorld::init(){if(!CCLayer::init()){returnfalse;}//获取可视区域尺寸大小CCSizemysize=CCDirector::sharedDirector()->getVisibleSize();//获取可视区域的原点位置CCPointorigin=CCDirector::sharedDirector()->getVisibleOrigin();//屏幕正中心位置CCPointmidPos=ccp(mysize.width/2,mysize.height/2);//显示按钮状态的标签displayLabeldisplayLabel=CCLabelTTF::create("NoEvent","MarkerFelt",32);displayLabel->setPosition(midPos+ccp(0,100));this->addChild(displayLabel);//按钮中的背景精灵CCScale9SpriteCCScale9Sprite*bgNormal=CCScale9Sprite::create("btnNormal.png");//正常背景CCScale9Sprite*bgHighlighted=CCScale9Sprite::create("btnHighlighted.png");//高亮背景//按钮中的标签CCLabelTTFCCLabelTTF*titleNormal=CCLabelTTF::create("ButtonisNormal!","MarkerFelt",30);CCLabelTTF*titleHighlighted=CCLabelTTF::create("ButtonisHighlighted!","MarkerFelt",30);//创建按钮CCControlButtonCCControlButton*btn=CCControlButton::create(titleNormal,bgNormal);btn->setPosition(midPos);this->addChild(btn);//设置按钮高亮时的状态btn->setTitleLabelForState(titleHighlighted,CCControlStateHighlighted);//高亮标签btn->setTitleColorForState(ccRED,CCControlStateHighlighted);//红色btn->setBackgroundSpriteForState(bgHighlighted,CCControlStateHighlighted);//高亮背景//写了这句话,反而大小被固定了。没有按照label的大小进行自动伸展了//btn->setPreferredSize(CCSizeMake(120,40));//绑定事件,用于显示按钮状态btn->addTargetWithActionForControlEvents(this,cccontrol_selector(HelloWorld::touchDownAction),CCControlEventTouchDown);//刚刚开始触摸按钮时btn->addTargetWithActionForControlEvents(this,cccontrol_selector(HelloWorld::touchDragInsideAction),CCControlEventTouchDragInside);//在内部拖动时(保持触摸状态下)btn->addTargetWithActionForControlEvents(this,cccontrol_selector(HelloWorld::touchDragOutsideAction),CCControlEventTouchDragOutside);//在外部拖动时(保持触摸状态下)btn->addTargetWithActionForControlEvents(this,cccontrol_selector(HelloWorld::touchDragEnterAction),CCControlEventTouchDragEnter);//拖动刚进入内部时(保持触摸状态下)btn->addTargetWithActionForControlEvents(this,cccontrol_selector(HelloWorld::touchDragExitAction),CCControlEventTouchDragExit);//拖动刚离开内部时(保持触摸状态下)btn->addTargetWithActionForControlEvents(this,cccontrol_selector(HelloWorld::touchUpInsideAction),CCControlEventTouchUpInside);//在内部抬起手指(保持触摸状态下)btn->addTargetWithActionForControlEvents(this,cccontrol_selector(HelloWorld::touchUpOutsideAction),CCControlEventTouchUpOutside);//在外部抬起手指(保持触摸状态下)btn->addTargetWithActionForControlEvents(this,cccontrol_selector(HelloWorld::touchCancelAction),CCControlEventTouchCancel);//取消触点returntrue;}//


5、实现按钮事件的回调函数

////刚刚开始触摸按钮时voidHelloWorld::touchDownAction(CCObject*senderz,CCControlEventcontrolEvent){displayLabel->setString("TouchDown");}//在内部拖动时(保持触摸状态下)voidHelloWorld::touchDragInsideAction(CCObject*sender,CCControlEventcontrolEvent){displayLabel->setString("DragInside");}//在外部拖动时(保持触摸状态下)voidHelloWorld::touchDragOutsideAction(CCObject*sender,CCControlEventcontrolEvent){displayLabel->setString("DragOutside");}//拖动刚进入内部时(保持触摸状态下)voidHelloWorld::touchDragEnterAction(CCObject*sender,CCControlEventcontrolEvent){displayLabel->setString("DragEnter");}//拖动刚离开内部时(保持触摸状态下)voidHelloWorld::touchDragExitAction(CCObject*sender,CCControlEventcontrolEvent){displayLabel->setString("DragExit");}//在内部抬起手指(保持触摸状态下)voidHelloWorld::touchUpInsideAction(CCObject*sender,CCControlEventcontrolEvent){displayLabel->setString("TouchUpInside.");}//在外部抬起手指(保持触摸状态下)voidHelloWorld::touchUpOutsideAction(CCObject*sender,CCControlEventcontrolEvent){displayLabel->setString("TouchUpOutside.");}//取消所有触摸voidHelloWorld::touchCancelAction(CCObject*sender,CCControlEventcontrolEvent){displayLabel->setString("TouchCancel");}//


6、运行结果


7、分析与总结

(1)本来一个这么小的按钮图片,这么变这么大了呢?这是因为当标签CCLabelTTF的大小大于按钮大小时,按钮就会自动进行伸展。

(2)我明明设置了高亮状态下,标签为titleHighlighted,且其标签内容应该显示“Button is Highlighted !”才对呀,为什么还是“Button is Normal”?。。。好吧,这个问题我也不知道。不过字体颜色,和按钮的背景精灵图确实是换掉了。

(3)至于按钮事件:

CCControlEventTouchDragEnter //拖动刚进入内部时(保持触摸状态下)

CCControlEventTouchDragExit //拖动刚离开内部时(保持触摸状态下)

不知道大家有没有观察到呢?因为只有在正好进入或离开按钮内部时才看得到效果,手一抖就变成DragInside或DragOutside了。