cocos2d-x 八(界面控件之CCControl控件)

CCControl控件也是cocos2d-x扩展控件中的一部分,包含了九宫格(nine pacth)按钮、滑动条、开关按钮、电位计按钮、步进器和颜色选择控件,这些也算是常用的控件了,下面是各个控件的使用方法及流程:

1.九宫格按钮

这是一种为了方便不失真缩放而诞生出的简洁型按钮,具体说来就是这种按钮使用的是纹理相对比较规则的图片,然后将图片划分为九个显示区域,在缩放按钮的时候,根据需要将这九个区域中的纹理按最佳比例进行延伸或者缩放,最后达到降低、甚至不失真的缩放效果。对应九宫格的类是CCScale9Sprite,它继承的是CCNodeRGBA,就是它负责将需要的图片按3X3的等份划分出九个区域,然后搭配CCControlButton这个按钮类即可制作出九宫格按钮,下面是官方原例Extension Test里抽出修改的代码:

//我把原来用的场景改成了层
class CCControlButtonTest_Event : public CCLayer
{
public:
    bool init();
    //这里定义了button的触摸事件
    void touchDownAction(CCObject *sender, CCControlEvent controlEvent);
    void touchDragInsideAction(CCObject *sender, CCControlEvent controlEvent);
    void touchDragOutsideAction(CCObject *sender, CCControlEvent controlEvent);
    void touchDragEnterAction(CCObject *sender, CCControlEvent controlEvent);
    void touchDragExitAction(CCObject *sender, CCControlEvent controlEvent);
    void touchUpInsideAction(CCObject *sender, CCControlEvent controlEvent);
    void touchUpOutsideAction(CCObject *sender, CCControlEvent controlEvent);
    void touchCancelAction(CCObject *sender, CCControlEvent controlEvent);
protected:
    CC_SYNTHESIZE_RETAIN(CCLabelTTF *, m_pDisplayValueLabel, DisplayValueLabel)
    CONTROL_SCENE_CREATE_FUNC(CCControlButtonTest_Event)
};

bool CCControlButtonTest_Event::init() {

	bool bRet = false;
    do 
    {
        //////////////////////////////////////////////////////////////////////////
        // super init first
        //////////////////////////////////////////////////////////////////////////

        CC_BREAK_IF(! CCLayer::init());
	
		CCSize Size = CCDirector::sharedDirector()->getWinSize();
        // Add the button 这里先设定了两个九宫格用来划分不同状态下按钮的图片区块
        CCScale9Sprite *backgroundButton = CCScale9Sprite::create("button.png");
        CCScale9Sprite *backgroundHighlightedButton = CCScale9Sprite::create("buttonHighlighted.png");
        //这个label是用来做caption标题的
        CCLabelTTF *titleButton = CCLabelTTF::create("Touch Me!", "Marker Felt", 30);

        titleButton->setColor(ccc3(159, 168, 176));
        //这里开始加入button控件,创建时引用了label和CCScale9Sprite
        CCControlButton *controlButton = CCControlButton::create(titleButton, backgroundButton);
        //这里用来设置按钮被触发状态(高亮状态)时的标题颜色和图片,这里可以看到引用的是另一个<span style="font-family: Arial, Helvetica, sans-serif;">CCScale9Sprite 
</span>        //在源码中还能看到其它状态的设置如:CCControlStateSelected、CCControlStateDisabled
        controlButton->setBackgroundSpriteForState(backgroundHighlightedButton, CCControlStateHighlighted);
        controlButton->setTitleColorForState(ccWHITE, CCControlStateHighlighted);
        //这里设置了锚点,用来设定按钮状态变化时的中心坐标
        controlButton->setAnchorPoint(ccp(0.5f, 1));
        controlButton->setPosition(ccp(Size.width / 2.0f,Size.height / 2.0f));
        addChild(controlButton, 1);

<span style="white-space: pre;">	</span>// Sets up event handlers 一大片触发事件,有点眼花……
        controlButton->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlButtonTest_Event::touchDownAction), CCControlEventTouchDown);
        controlButton->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlButtonTest_Event::touchDragInsideAction), CCControlEventTouchDragInside);
        controlButton->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlButtonTest_Event::touchDragOutsideAction), CCControlEventTouchDragOutside);
        controlButton->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlButtonTest_Event::touchDragEnterAction), CCControlEventTouchDragEnter);
        controlButton->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlButtonTest_Event::touchDragExitAction), CCControlEventTouchDragExit);
        controlButton->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlButtonTest_Event::touchUpInsideAction), CCControlEventTouchUpInside);
        controlButton->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlButtonTest_Event::touchUpOutsideAction), CCControlEventTouchUpOutside);
        controlButton->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlButtonTest_Event::touchCancelAction), CCControlEventTouchCancel);
		        bRet = true;
    } while (0);
return bRet;

}
 


	
	
	

触发事件代码和层的创建添加就不多写了……

再来看看Slider滑动条,这个应用也是很普遍的,什么设置音量,显示参数之类的……其实它的用法和平常用的差不多,下面是代码:

//添加一个滑动条
class CCControlSliderTest : public cocos2d::CCLayer
{
public:
    bool init();
    //这个就是滑动时的事件了
    void valueChanged(CCObject *sender, CCControlEvent controlEvent);

    cocos2d::CCLabelTTF* m_pDisplayValueLabel;
    CREATE_FUNC(CCControlSliderTest)
};

//这里代码照抄
bool CCControlSliderTest::init()
{
	bool bRet = false;
    do 
    {
        //////////////////////////////////////////////////////////////////////////
        // super init first
        //////////////////////////////////////////////////////////////////////////

        CC_BREAK_IF(! CCLayer::init());
        CCSize screenSize = CCDirector::sharedDirector()->getWinSize();

        // Add a label in which the slider value will be displayed
        m_pDisplayValueLabel = CCLabelTTF::create("Move the slider thumb!\nThe lower slider is restricted." ,"Marker Felt", 18);
        m_pDisplayValueLabel->retain();
        m_pDisplayValueLabel->setAnchorPoint(ccp(0.5f, -1.0f));
        m_pDisplayValueLabel->setPosition(ccp(screenSize.width / 1.7f, screenSize.height / 2.0f));
        addChild(m_pDisplayValueLabel);

        // Add the slider,这里的三张图片分别对应于滑动条的三个部分
        CCControlSlider *slider = CCControlSlider::create("sliderTrack.png","sliderProgress.png" ,"sliderThumb.png");
        slider->setAnchorPoint(ccp(0.5f, 1.0f));
        //设定最大最小值
        slider->setMinimumValue(0.0f); // Sets the min value of range
        slider->setMaximumValue(5.0f); // Sets the max value of range
        slider->setPosition(ccp(screenSize.width / 2.0f, screenSize.height / 2.0f + 16));
        //给控件加个标识号作索引用
		slider->setTag(1);

        // When the value of the slider will change, the given selector will be call
        //这里和按钮一样,绑定一个拖动后的触发事件
        slider->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlSliderTest::valueChanged), CCControlEventValueChanged);

		CCControlSlider *restrictSlider = CCControlSlider::create("sliderTrack.png","sliderProgress.png" ,"sliderThumb.png");
        restrictSlider->setAnchorPoint(ccp(0.5f, 1.0f));
        restrictSlider->setMinimumValue(0.0f); // Sets the min value of range
        restrictSlider->setMaximumValue(5.0f); // Sets the max value of range
        //这里设置的是允许的最大、最小拖动值,也就是说最大值只能拖到4……
		restrictSlider->setMaximumAllowedValue(4.0f);
		restrictSlider->setMinimumAllowedValue(1.5f);
		restrictSlider->setValue(3.0f);
        restrictSlider->setPosition(ccp(screenSize.width / 2.0f, screenSize.height / 2.0f - 24));
       
		restrictSlider->setTag(2);

	//same with restricted
		restrictSlider->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlSliderTest::valueChanged), CCControlEventValueChanged);

        addChild(slider);    
		addChild(restrictSlider);

        bRet = true;
    } while (0);
return bRet;

}

void CCControlSliderTest::valueChanged(CCObject *sender, CCControlEvent controlEvent)
{
		
    CCControlSlider* pSlider = (CCControlSlider*)sender;
    // Change value of label.这里根据索引来显示当前拖动的滑动条的数值
	if(pSlider->getTag() == 1)
		m_pDisplayValueLabel->setString(CCString::createWithFormat("Upper slider value = %.02f", pSlider->getValue())->getCString());  
	if(pSlider->getTag() == 2)
		m_pDisplayValueLabel->setString(CCString::createWithFormat("Lower slider value = %.02f", pSlider->getValue())->getCString()); 
}
继续->开关按钮,代码:
class CCControlSwitchTest : public <span style="font-family: Arial, Helvetica, sans-serif;">cocos2d::CCLayer</span>

{
public:
    bool init();
    /** Callback for the change value. */
    void valueChanged(CCObject* sender, CCControlEvent controlEvent);
    CCLabelTTF *m_pDisplayValueLabel;
    CREATE_FUNC(CCControlSwitchTest)
};
//开关按钮
bool CCControlSwitchTest::init()
{
	bool bRet = false;
    do 
    {
        //////////////////////////////////////////////////////////////////////////
        // super init first
        //////////////////////////////////////////////////////////////////////////

        CC_BREAK_IF(! CCLayer::init());
        CCSize screenSize = CCDirector::sharedDirector()->getWinSize();

        CCNode *layer = CCNode::create();
        layer->setPosition(ccp (screenSize.width / 2-120, screenSize.height / 2+100));
		//这里又多加了一个子层用来显示开关按钮的状态
        addChild(layer, 1);
        
        double layer_width = 0;
        
        // Add the black background for the text
        CCScale9Sprite *background = CCScale9Sprite::create("buttonBackground.png");
        background->setContentSize(CCSizeMake(80, 50));
        background->setPosition(ccp(layer_width + background->getContentSize().width / 2.0f, 0));
        layer->addChild(background);
        
        layer_width += background->getContentSize().width;
        
        m_pDisplayValueLabel  = CCLabelTTF::create("#color" ,"Marker Felt" ,30);
        m_pDisplayValueLabel->retain();

        m_pDisplayValueLabel->setPosition(background->getPosition());
        layer->addChild(m_pDisplayValueLabel);
        
        // Create the switch这里需要四平张图片来显示控件各部分
		//创建方式还有另一种,就是不加标签显示,去掉最后两个参数即是
        CCControlSwitch *switchControl = CCControlSwitch::create
            (
                CCSprite::create("switch-mask.png"),
                CCSprite::create("switch-on.png"),
                CCSprite::create("switch-off.png"),
                CCSprite::create("switch-thumb.png"),
                CCLabelTTF::create("On", "Arial-BoldMT", 16),
                CCLabelTTF::create("Off", "Arial-BoldMT", 16)
            );
        switchControl->setPosition(ccp (layer_width + 10 + switchControl->getContentSize().width / 2, 0));
        layer->addChild(switchControl);
       //绑定事件
        switchControl->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlSwitchTest::valueChanged), CCControlEventValueChanged);
        
        // Set the layer size
        layer->setContentSize(CCSizeMake(layer_width, 0));
        layer->setAnchorPoint(ccp (0.5f, 0.5f));
        
        // Update the value label和button一样,它也有很多状态参数,这里便是指定在值产生变化的时候执行valueChanged中的代码
        valueChanged(switchControl, CCControlEventValueChanged);
        bRet = true;
    } while (0);
return bRet;
}

void CCControlSwitchTest::valueChanged(CCObject* sender, CCControlEvent controlEvent)
{
	//拿到操作对象
    CCControlSwitch* pSwitch = (CCControlSwitch*)sender;
	//根据按钮当前的状态显示标签内容
    if (pSwitch->isOn())
    {
        m_pDisplayValueLabel->setString("On");
    } 
    else
    {
        m_pDisplayValueLabel->setString("Off");
    }
}

继续->步进器,这个东西也是很常用的,常用用于参数微调,看代码:

//步进器
class CCControlStepperTest : public cocos2d::CCLayer
{
public:
&nbsp; &nbsp; bool init();
&nbsp; &nbsp; // Creates and returns a new ControlStepper.&nbsp;
<span style="white-space: pre;">	</span>cocos2d::extension::CCControlStepper* makeControlStepper();
<span style="white-space: pre;">	</span>virtual void onExit();
&nbsp; &nbsp; // Callback for the change value.&nbsp;
&nbsp; &nbsp; void valueChanged(CCObject *sender, CCControlEvent controlEvent);
<span style="white-space: pre;">	</span>protected:
<span style="white-space: pre;">	</span>// 在setDisplayValueLabel的时候,调用原有m_pDisplayValueLabel的release,并且调用新值的的retain,专用于声明protected的变量
<span style="white-space: pre;">	</span>//具体请进源码里参考对此宏的定义
&nbsp; &nbsp; CC_SYNTHESIZE_RETAIN(cocos2d::CCLabelTTF*, m_pDisplayValueLabel, DisplayValueLabel)
&nbsp; &nbsp; CREATE_FUNC(CCControlStepperTest)
};

//添加一个步进器
bool CCControlStepperTest::init()
{
	bool bRet = false;
    do 
    {
        //////////////////////////////////////////////////////////////////////////
        // super init first
        //////////////////////////////////////////////////////////////////////////

        CC_BREAK_IF(! CCLayer::init());
		//初始化
	    m_pDisplayValueLabel=NULL;

        CCSize screenSize = CCDirector::sharedDirector()->getWinSize();
        
        CCNode *layer = CCNode::create();
        layer->setPosition(ccp (screenSize.width / 2+100, screenSize.height / 2+100));
        this->addChild(layer, 1);
        
        double layer_width          = 0;
        
        // Add the black background for the text
        CCScale9Sprite *background  = CCScale9Sprite::create("buttonBackground.png");
        background->setContentSize(CCSizeMake(100, 50));
        background->setPosition(ccp(layer_width + background->getContentSize().width / 2.0f, 0));
        layer->addChild(background);

        //使用setter创建一个用于显示当前值的label
        this->setDisplayValueLabel(CCLabelTTF::create("0", "HelveticaNeue-Bold", 30));
        m_pDisplayValueLabel->setPosition(background->getPosition());
        layer->addChild(m_pDisplayValueLabel);
        
        layer_width  += background->getContentSize().width;
        //调用创建
        CCControlStepper *stepper   = this->makeControlStepper();
        stepper->setPosition(ccp (layer_width + 10 + stepper->getContentSize().width / 2, 0));
        stepper->addTargetWithActionForControlEvents(this, cccontrol_selector(CCControlStepperTest::valueChanged), CCControlEventValueChanged);
        layer->addChild(stepper);
        
        layer_width                 += stepper->getContentSize().width;
        
        // Set the layer size
        layer->setContentSize(CCSizeMake(layer_width, 0));
        layer->setAnchorPoint(ccp (0.5f, 0.5f));
        
        // Update the value label
        this->valueChanged(stepper, CCControlEventValueChanged);
		bRet = true;
    } while (0);
return bRet;
}
//这里把创建步进器的过程独立出来了
CCControlStepper *CCControlStepperTest::makeControlStepper()
{
    CCSprite *minusSprite       = CCSprite::create("stepper-minus.png");
    CCSprite *plusSprite        = CCSprite::create("stepper-plus.png");
    
    return CCControlStepper::create(minusSprite, plusSprite);
}

void CCControlStepperTest::valueChanged(CCObject *sender, CCControlEvent controlEvent)
{
    CCControlStepper* pControl = (CCControlStepper*)sender;
    // Change value of label.
    m_pDisplayValueLabel->setString(CCString::createWithFormat("%0.02f", (float)pControl->getValue())->getCString());	
}

void CCControlStepperTest::onExit(){
	CC_SAFE_RELEASE(m_pDisplayValueLabel);
}
 看了下源码中还定义有一对宏:


  1. CC_SYNTHESIZE_RETAIN(CCSprite*, m_pMinusSprite, MinusSprite)  
  2. CC_SYNTHESIZE_RETAIN(CCSprite*, m_pPlusSprite, PlusSprite)  


CC_SYNTHESIZE_RETAIN(CCSprite*, m_pMinusSprite, MinusSprite)
CC_SYNTHESIZE_RETAIN(CCSprite*, m_pPlusSprite, PlusSprite)

用这个的话应该就能用来操控自定义的精灵属性了(貌似很有用^_^)……,人懒啊……所以就不测试了……

官方原例中还有个很酷的电位计按钮,其实使用和步进器是一样的,就不写了。另还有颜色拾取器也自己去看吧,估计我很难用到这东西……

还是推荐一篇文章,应该多看看cocos2d-x的内存管理(我总是自以为是的释放然后报错是……):http://blog.csdn.net/honghaier/article/details/8160519 

下面是源代码下载:http://download.csdn.net/detail/cyistudio/5459721