Cocos2d-x学习笔记(十二)CCMenuItem详解
来源:互联网 发布:铝材下料软件 编辑:程序博客网 时间:2024/06/06 04:38
原创文章,转载请注明出处:http://blog.csdn.net/sfh366958228/article/details/38948661
前言
我们上一篇笔记对CCMenu的实现进行了分析,这一节我们来看看CCMenuItem。
头文件
class CC_DLL CCMenuItem : public CCNodeRGBA{protected: /** whether or not the item is selected @since v0.8.2 */ bool m_bSelected; // 是否被选中 bool m_bEnabled; // 是否可用public: CCMenuItem() : m_bSelected(false) , m_bEnabled(false) , m_pListener(NULL) , m_pfnSelector(NULL) , m_nScriptTapHandler(0) {} virtual ~CCMenuItem(); // 默认创建方法 static CCMenuItem* create(); // 根据一个目标节点和选择事件创建 static CCMenuItem* create(CCObject *rec, SEL_MenuHandler selector); // 根据一个目标节点和选择事件进行初始化 bool initWithTarget(CCObject *rec, SEL_MenuHandler selector); // 返回当前菜单的矩形 CCRect rect(); // 激活当前的菜单项 virtual void activate(); // 将当前菜单项置于被选中时状态 virtual void selected(); // 取消当前菜单项选中状态 virtual void unselected(); /** Register menu handler script function */ virtual void registerScriptTapHandler(int nHandler); virtual void unregisterScriptTapHandler(void); int getScriptTapHandler() { return m_nScriptTapHandler; }; // 获取菜单项是否可用 virtual bool isEnabled(); // 设置菜单项是否可用 virtual void setEnabled(bool value); virtual bool isSelected(); // 设置菜单项的目标节点和选择事件 void setTarget(CCObject *rec, SEL_MenuHandler selector);protected: CCObject* m_pListener; // 目标节点 SEL_MenuHandler m_pfnSelector; // 选择事件 int m_nScriptTapHandler;};/** @brief An abstract class for "label" CCMenuItemLabel items Any CCNode that supports the CCLabelProtocol protocol can be added. Supported nodes: - CCBitmapFontAtlas - CCLabelAtlas - CCLabelTTF */class CC_DLL CCMenuItemLabel : public CCMenuItem{ /** the color that will be used to disable the item */ CC_PROPERTY_PASS_BY_REF(ccColor3B, m_tDisabledColor, DisabledColor); /** Label that is rendered. It can be any CCNode that implements the CCLabelProtocol */ CC_PROPERTY(CCNode*, m_pLabel, Label);public: CCMenuItemLabel() : m_pLabel(NULL) , m_fOriginalScale(0.0) {} virtual ~CCMenuItemLabel(); // 根据CCLabel、目标节点、点击事件创建一个紫菜单项 static CCMenuItemLabel * create(CCNode*label, CCObject* target, SEL_MenuHandler selector); // 根据一个CCLabel创建一个子菜单项 static CCMenuItemLabel* create(CCNode *label); // 初始化子菜单项 bool initWithLabel(CCNode* label, CCObject* target, SEL_MenuHandler selector); // 设置菜单项显示文字 void setString(const char * label); // 基类方法 virtual void activate(); virtual void selected(); virtual void unselected(); // 设置子菜单项是否可用 virtual void setEnabled(bool enabled); protected: ccColor3B m_tColorBackup; // 备份颜色 float m_fOriginalScale; // 缩放比例};/** @brief A CCMenuItemAtlasFont Helper class that creates a MenuItemLabel class with a LabelAtlas */class CC_DLL CCMenuItemAtlasFont : public CCMenuItemLabel{public: CCMenuItemAtlasFont(){} virtual ~CCMenuItemAtlasFont(){} static CCMenuItemAtlasFont* create(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap); static CCMenuItemAtlasFont* create(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap, CCObject* target, SEL_MenuHandler selector); bool initWithString(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap, CCObject* target, SEL_MenuHandler selector);};class CC_DLL CCMenuItemFont : public CCMenuItemLabel{public: CCMenuItemFont() : m_uFontSize(0), m_strFontName(""){} virtual ~CCMenuItemFont(){} // 设置/获取全局字体字号 static void setFontSize(unsigned int s); static unsigned int fontSize(); // 设置/获取全局字体名称 static void setFontName(const char *name); static const char *fontName(); // 仅通过文字创建一个子菜单项 static CCMenuItemFont * create(const char *value); // 通过文字、目标节点、点击事件创建一个子菜单项 static CCMenuItemFont * create(const char *value, CCObject* target, SEL_MenuHandler selector); // 初始化子菜单项 bool initWithString(const char *value, CCObject* target, SEL_MenuHandler selector); // 设置/获取当前字体大小 void setFontSizeObj(unsigned int s); unsigned int fontSizeObj(); // 设置/获取当前字体名称 void setFontNameObj(const char* name); const char* fontNameObj(); protected: void recreateLabel(); // 重新设置Label unsigned int m_uFontSize; // 字体大小 std::string m_strFontName; // 字体名称};// Sprite子菜单项class CC_DLL CCMenuItemSprite : public CCMenuItem{ CC_PROPERTY(CCNode*, m_pNormalImage, NormalImage); CC_PROPERTY(CCNode*, m_pSelectedImage, SelectedImage); CC_PROPERTY(CCNode*, m_pDisabledImage, DisabledImage);public: CCMenuItemSprite() :m_pNormalImage(NULL) ,m_pSelectedImage(NULL) ,m_pDisabledImage(NULL) {} /** * 创建一个子菜单项 * * @param normalSprite 一般情况下的精灵 * @param selectedSprite 选中情况下的精灵 * @param disabledSprite 不可用情况下的精灵 */ static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite = NULL); static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCObject* target, SEL_MenuHandler selector); static CCMenuItemSprite * create(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite, CCObject* target, SEL_MenuHandler selector); // 初始化子菜单项 bool initWithNormalSprite(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite, CCObject* target, SEL_MenuHandler selector); // virtual void selected(); virtual void unselected(); virtual void setEnabled(bool bEnabled); protected: virtual void updateImagesVisibility();};// Image子菜单项class CC_DLL CCMenuItemImage : public CCMenuItemSprite{public: CCMenuItemImage(){} virtual ~CCMenuItemImage(){} /** * 创建一个子菜单项 * * @param normalImage 一般情况下的图片地址 * @param selectedImage 选中情况下的图片地址 * @param disabledImage 不可用情况下的图片地址 */ static CCMenuItemImage* create(const char *normalImage, const char *selectedImage); static CCMenuItemImage* create(const char *normalImage, const char *selectedImage, const char *disabledImage); static CCMenuItemImage* create(const char *normalImage, const char *selectedImage, CCObject* target, SEL_MenuHandler selector); static CCMenuItemImage* create(const char *normalImage, const char *selectedImage, const char *disabledImage, CCObject* target, SEL_MenuHandler selector); // 初始化一个子菜单项 bool init(); bool initWithNormalImage(const char *normalImage, const char *selectedImage, const char *disabledImage, CCObject* target, SEL_MenuHandler selector); // 设置一般/选中/不可用状态下的Sprite帧 void setNormalSpriteFrame(CCSpriteFrame* frame); void setSelectedSpriteFrame(CCSpriteFrame* frame); void setDisabledSpriteFrame(CCSpriteFrame* frame); // 创建一个空子菜单项 static CCMenuItemImage* create();};// Toggle子菜单项class CC_DLL CCMenuItemToggle : public CCMenuItem{ CC_PROPERTY(unsigned int, m_uSelectedIndex, SelectedIndex); CC_PROPERTY(CCArray*, m_pSubItems, SubItems);public: CCMenuItemToggle() : m_uSelectedIndex(0) , m_pSubItems(NULL) {} virtual ~CCMenuItemToggle(); // 通过目标节点、点击事件、子菜单项数组创建一个子菜单项 static CCMenuItemToggle * createWithTarget(CCObject* target, SEL_MenuHandler selector, CCArray* menuItems); // 通过目标节点、点击事件、子菜单项序列创建一个子菜单项 static CCMenuItemToggle* createWithTarget(CCObject* target, SEL_MenuHandler selector, CCMenuItem* item, ...); // 通过一个子菜单项创建一个子菜单项 static CCMenuItemToggle* create(CCMenuItem *item); // 创建一个空子菜单项 static CCMenuItemToggle* create(); // 初始化子菜单项 bool initWithTarget(CCObject* target, SEL_MenuHandler selector, CCMenuItem* item, va_list args); bool initWithItem(CCMenuItem *item); // 添加一个子菜单项 void addSubItem(CCMenuItem *item); // 返回当前选中的子菜单项 CCMenuItem* selectedItem(); // 基类方法 virtual void activate(); virtual void selected(); virtual void unselected(); virtual void setEnabled(bool var); };
通过头文件中描述我们不难发现,存在一个名为CCMenuItem的基类,来实现所有子菜单项的基本功能(继承自CCNode),然后由它又派生出了CCMenuItemLabel、CCMenuItemAtlasFont、CCMenuItemFont、CCMenuItemSprite、CCMenuItemImage、CCMenuItemToggle六种子菜单项:
CCMenuItemLabel是依据一个Label来创建的子菜单项,用于显示文本,也是CCMenuItemAtlasFont和CCMenuItemFont的基类
CCMenuItemAtlasFont是用于显示图片字体的子菜单项
CCMenuItemFont是用于创建一般文字子菜单项,极其简易,也可以自定义字体
CCMenuItemSprite是通过Sprite来创建子菜单项,需要传递一般状态、选中状态和不可用状态三种状态的Sprite
CCMenuItemImage是通过图片地址来创建子菜单项,也需要传递三种状态,它继承自CCMenuItemSprite,但相对于CCMenuItem而言操作更加简便
CCMenuItemToggle是一个比较有意思的子菜单项,它需要传递一系列子菜单项作为参数,用于实现点击后替换菜单项的效果,例如里面有A、B、C三个子菜单项,默认情况下是A,点一次之后变成了B,再点一次变成C,再点一次又变回A。
可是具体子菜单项又是怎样实现的呢?我们分析分析~
实现文件
static unsigned int _globalFontSize = kCCItemSize;static std::string _globalFontName = "Marker Felt";static bool _globalFontNameRelease = false;const unsigned int kCurrentItem = 0xc0c05001;const unsigned int kZoomActionTag = 0xc0c05002;const unsigned int kNormalTag = 0x1;const unsigned int kSelectedTag = 0x2;const unsigned int kDisableTag = 0x3;//// CCMenuItem//CCMenuItem* CCMenuItem::create(){ return CCMenuItem::create(NULL, NULL);}CCMenuItem* CCMenuItem::create(CCObject *rec, SEL_MenuHandler selector){ CCMenuItem *pRet = new CCMenuItem(); // 通过构造函数创建一个默认的子菜单项 pRet->initWithTarget(rec, selector); // 初始化 pRet->autorelease(); // 添加到自动释放池中 return pRet;}bool CCMenuItem::initWithTarget(CCObject *rec, SEL_MenuHandler selector){ setAnchorPoint(ccp(0.5f, 0.5f)); // 设置锚点为中心 m_pListener = rec; // 设置监听器,即子菜单项所在目标节点 m_pfnSelector = selector; // 设置点击事件回调函数指针 m_bEnabled = true; // 设置为可用 m_bSelected = false; // 设置为未选中状态 return true;}CCMenuItem::~CCMenuItem(){ unregisterScriptTapHandler();}void CCMenuItem::selected(){ m_bSelected = true; // 修改为选中状态}void CCMenuItem::unselected(){ m_bSelected = false; // 修改为不可用状态}void CCMenuItem::registerScriptTapHandler(int nHandler){ unregisterScriptTapHandler(); m_nScriptTapHandler = nHandler; LUALOG("[LUA] Add CCMenuItem script handler: %d", m_nScriptTapHandler);}void CCMenuItem::unregisterScriptTapHandler(void){ if (m_nScriptTapHandler) { CCScriptEngineManager::sharedManager()->getScriptEngine()->removeScriptHandler(m_nScriptTapHandler); LUALOG("[LUA] Remove CCMenuItem script handler: %d", m_nScriptTapHandler); m_nScriptTapHandler = 0; }}void CCMenuItem::activate(){ if (m_bEnabled) // 如果当前子菜单项可用 { if (m_pListener && m_pfnSelector) // 且目标节点及点击事件存在 { (m_pListener->*m_pfnSelector)(this); } if (kScriptTypeNone != m_eScriptType) { CCScriptEngineManager::sharedManager()->getScriptEngine()->executeMenuItemEvent(this); } }}void CCMenuItem::setEnabled(bool enabled){ m_bEnabled = enabled; // 设置可用状态}bool CCMenuItem::isEnabled(){ return m_bEnabled; // 返回可用状态}CCRect CCMenuItem::rect(){ return CCRectMake( m_obPosition.x - m_obContentSize.width * m_obAnchorPoint.x, m_obPosition.y - m_obContentSize.height * m_obAnchorPoint.y, m_obContentSize.width, m_obContentSize.height);}bool CCMenuItem::isSelected(){ return m_bSelected; // 返回选中状态}void CCMenuItem::setTarget(CCObject *rec, SEL_MenuHandler selector){ m_pListener = rec; m_pfnSelector = selector;}////CCMenuItemLabel//const ccColor3B& CCMenuItemLabel::getDisabledColor(){ return m_tDisabledColor; // 返回不可用该状态文字颜色}void CCMenuItemLabel::setDisabledColor(const ccColor3B& var){ m_tDisabledColor = var; // 设置不可用状态下文字颜色}CCNode *CCMenuItemLabel::getLabel(){ return m_pLabel; // 返回子菜单项的Label}void CCMenuItemLabel::setLabel(CCNode* var){ if (var) // 如果待设置Label不为空 { addChild(var); // 添加Label var->setAnchorPoint(ccp(0, 0)); // 将锚点设置为左下角 setContentSize(var->getContentSize()); // 将子菜单项大小设置为Label大小 } if (m_pLabel) // 如果当前Label不为空 { removeChild(m_pLabel, true); // 移除并清空当前Label } m_pLabel = var; // 重新复制Label}CCMenuItemLabel * CCMenuItemLabel::create(CCNode*label, CCObject* target, SEL_MenuHandler selector){ CCMenuItemLabel *pRet = new CCMenuItemLabel(); pRet->initWithLabel(label, target, selector); pRet->autorelease(); return pRet;}CCMenuItemLabel* CCMenuItemLabel::create(CCNode *label){ CCMenuItemLabel *pRet = new CCMenuItemLabel(); pRet->initWithLabel(label, NULL, NULL); pRet->autorelease(); return pRet;}bool CCMenuItemLabel::initWithLabel(CCNode* label, CCObject* target, SEL_MenuHandler selector){ CCMenuItem::initWithTarget(target, selector); m_fOriginalScale = 1.0f; // 默认缩放系数为1,代表没有缩放 m_tColorBackup = ccWHITE; // 默认字体颜色为白色,本分一下 setDisabledColor(ccc3(126,126,126)); // 设置不可用状态文字 this->setLabel(label); // 设置Label setCascadeColorEnabled(true); // 后续Label中讲到 setCascadeOpacityEnabled(true); return true;}CCMenuItemLabel::~CCMenuItemLabel(){}void CCMenuItemLabel::setString(const char * label){ dynamic_cast<CCLabelProtocol*>(m_pLabel)->setString(label); // 设置Label文字 this->setContentSize(m_pLabel->getContentSize()); // 重新设置子菜单项大小}void CCMenuItemLabel::activate(){ if(m_bEnabled) { this->stopAllActions(); // 停止所有动作 this->setScale( m_fOriginalScale ); // 设为默认缩放 CCMenuItem::activate(); // 调用基类的方法 }}void CCMenuItemLabel::selected(){ if(m_bEnabled) // 如果子菜单项可用才执行随后的方法 { CCMenuItem::selected(); CCAction *action = getActionByTag(kZoomActionTag); // 获取缩放动作 if (action) // 如果正在执行动作 { this->stopAction(action); // 停止动作 } else { m_fOriginalScale = this->getScale(); // 保存当前大小 } CCAction *zoomAction = CCScaleTo::create(0.1f, m_fOriginalScale * 1.2f); // 创建放大动作 zoomAction->setTag(kZoomActionTag); // 设置Tag this->runAction(zoomAction); // 执行缩放动作 }}void CCMenuItemLabel::unselected(){ if(m_bEnabled) { CCMenuItem::unselected(); // 调用基类方法 this->stopActionByTag(kZoomActionTag); // 停止缩放动作 CCAction *zoomAction = CCScaleTo::create(0.1f, m_fOriginalScale); // 创建缩小动作 zoomAction->setTag(kZoomActionTag); this->runAction(zoomAction); }}void CCMenuItemLabel::setEnabled(bool enabled){ if( m_bEnabled != enabled ) // 如果待设置状态与当前状态不一样才执行操作 { if(enabled == false) // 如果状态为不可用,则先备份当前可用颜色,然后将Label设置为不可用颜色 { m_tColorBackup = dynamic_cast<CCRGBAProtocol*>(m_pLabel)->getColor(); dynamic_cast<CCRGBAProtocol*>(m_pLabel)->setColor(m_tDisabledColor); } else { // 将Label恢复为备份颜色 dynamic_cast<CCRGBAProtocol*>(m_pLabel)->setColor(m_tColorBackup); } } CCMenuItem::setEnabled(enabled); // 设置为不可用}////CCMenuItemAtlasFont//CCMenuItemAtlasFont * CCMenuItemAtlasFont::create(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap){ return CCMenuItemAtlasFont::create(value, charMapFile, itemWidth, itemHeight, startCharMap, NULL, NULL);}CCMenuItemAtlasFont * CCMenuItemAtlasFont::create(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap, CCObject* target, SEL_MenuHandler selector){ CCMenuItemAtlasFont *pRet = new CCMenuItemAtlasFont(); pRet->initWithString(value, charMapFile, itemWidth, itemHeight, startCharMap, target, selector); pRet->autorelease(); return pRet;}bool CCMenuItemAtlasFont::initWithString(const char *value, const char *charMapFile, int itemWidth, int itemHeight, char startCharMap, CCObject* target, SEL_MenuHandler selector){ CCAssert( value != NULL && strlen(value) != 0, "value length must be greater than 0"); CCLabelAtlas *label = new CCLabelAtlas(); label->initWithString(value, charMapFile, itemWidth, itemHeight, startCharMap); label->autorelease(); if (CCMenuItemLabel::initWithLabel(label, target, selector)) { // do something ? } return true;}////CCMenuItemFont//void CCMenuItemFont::setFontSize(unsigned int s){ _globalFontSize = s;}unsigned int CCMenuItemFont::fontSize(){ return _globalFontSize;}void CCMenuItemFont::setFontName(const char *name){ if (_globalFontNameRelease) // 如果当前已有字体 { _globalFontName.clear(); // 清空字体名称 } _globalFontName = name; // 重新赋值字体名称 _globalFontNameRelease = true; // 标记为已有字体}const char * CCMenuItemFont::fontName(){ return _globalFontName.c_str();}CCMenuItemFont * CCMenuItemFont::create(const char *value, CCObject* target, SEL_MenuHandler selector){ CCMenuItemFont *pRet = new CCMenuItemFont(); pRet->initWithString(value, target, selector); pRet->autorelease(); return pRet;}CCMenuItemFont * CCMenuItemFont::create(const char *value){ CCMenuItemFont *pRet = new CCMenuItemFont(); pRet->initWithString(value, NULL, NULL); pRet->autorelease(); return pRet;}bool CCMenuItemFont::initWithString(const char *value, CCObject* target, SEL_MenuHandler selector){ // 确保传参有效 CCAssert( value != NULL && strlen(value) != 0, "Value length must be greater than 0"); m_strFontName = _globalFontName; m_uFontSize = _globalFontSize; CCLabelTTF *label = CCLabelTTF::create(value, m_strFontName.c_str(), (float)m_uFontSize); if (CCMenuItemLabel::initWithLabel(label, target, selector)) { // do something ? } return true;}void CCMenuItemFont::recreateLabel(){ // 重新创建一个Label,然后设置 CCLabelTTF *label = CCLabelTTF::create(dynamic_cast<CCLabelProtocol*>(m_pLabel)->getString(), m_strFontName.c_str(), (float)m_uFontSize); this->setLabel(label);}void CCMenuItemFont::setFontSizeObj(unsigned int s){ //设置字体大小后重新创建 m_uFontSize = s; recreateLabel();}unsigned int CCMenuItemFont::fontSizeObj(){ return m_uFontSize;}void CCMenuItemFont::setFontNameObj(const char* name){ m_strFontName = name; recreateLabel();}const char* CCMenuItemFont::fontNameObj(){ return m_strFontName.c_str();}////CCMenuItemSprite//CCNode * CCMenuItemSprite::getNormalImage(){ return m_pNormalImage;}void CCMenuItemSprite::setNormalImage(CCNode* pImage){ if (pImage != m_pNormalImage) // 如果需要替换的节点和当前节点不同 { if (pImage) // 如果节点不为空 { addChild(pImage, 0, kNormalTag); // 添加节点 pImage->setAnchorPoint(ccp(0, 0)); // 设置锚点为左下角 } if (m_pNormalImage) // 移除之前的一般状态Sprite { removeChild(m_pNormalImage, true); } m_pNormalImage = pImage; // 设置一般状态Sprite this->setContentSize(m_pNormalImage->getContentSize()); // 重置大小 this->updateImagesVisibility(); // 刷新可见性 }}CCNode * CCMenuItemSprite::getSelectedImage(){ return m_pSelectedImage;}void CCMenuItemSprite::setSelectedImage(CCNode* pImage){ // 同setNormalImage if (pImage != m_pNormalImage) { if (pImage) { addChild(pImage, 0, kSelectedTag); pImage->setAnchorPoint(ccp(0, 0)); } if (m_pSelectedImage) { removeChild(m_pSelectedImage, true); } m_pSelectedImage = pImage; this->updateImagesVisibility(); }}CCNode * CCMenuItemSprite::getDisabledImage(){ return m_pDisabledImage;}void CCMenuItemSprite::setDisabledImage(CCNode* pImage){ // 同setNormalImage if (pImage != m_pNormalImage) { if (pImage) { addChild(pImage, 0, kDisableTag); pImage->setAnchorPoint(ccp(0, 0)); } if (m_pDisabledImage) { removeChild(m_pDisabledImage, true); } m_pDisabledImage = pImage; this->updateImagesVisibility(); }}////CCMenuItemSprite//CCMenuItemSprite * CCMenuItemSprite::create(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite){ return CCMenuItemSprite::create(normalSprite, selectedSprite, disabledSprite, NULL, NULL);}CCMenuItemSprite * CCMenuItemSprite::create(CCNode* normalSprite, CCNode* selectedSprite, CCObject* target, SEL_MenuHandler selector){ return CCMenuItemSprite::create(normalSprite, selectedSprite, NULL, target, selector);}CCMenuItemSprite * CCMenuItemSprite::create(CCNode *normalSprite, CCNode *selectedSprite, CCNode *disabledSprite, CCObject *target, SEL_MenuHandler selector){ CCMenuItemSprite *pRet = new CCMenuItemSprite(); pRet->initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, target, selector); pRet->autorelease(); return pRet;}bool CCMenuItemSprite::initWithNormalSprite(CCNode* normalSprite, CCNode* selectedSprite, CCNode* disabledSprite, CCObject* target, SEL_MenuHandler selector){ CCMenuItem::initWithTarget(target, selector); setNormalImage(normalSprite); setSelectedImage(selectedSprite); setDisabledImage(disabledSprite); if(m_pNormalImage) { this->setContentSize(m_pNormalImage->getContentSize()); } setCascadeColorEnabled(true); setCascadeOpacityEnabled(true); return true;}/** @since v0.99.5 */void CCMenuItemSprite::selected(){ CCMenuItem::selected(); // 调用基类方法 if (m_pNormalImage) // 如果一般状态Sprite不为空 { if (m_pDisabledImage) // 如果不可用状态Sprite不为空 { m_pDisabledImage->setVisible(false); // 不可用状态Sprite设为不可见 } if (m_pSelectedImage) // 如果选中状态Sprite不为空 { m_pNormalImage->setVisible(false); // 一般状态Sprite设为不可见 m_pSelectedImage->setVisible(true); // 选中状态Sprite设为可见 } else { m_pNormalImage->setVisible(true); // 一般状态Sprite设为可见 } }}void CCMenuItemSprite::unselected(){ // 同selected CCMenuItem::unselected(); if (m_pNormalImage) { m_pNormalImage->setVisible(true); if (m_pSelectedImage) { m_pSelectedImage->setVisible(false); } if (m_pDisabledImage) { m_pDisabledImage->setVisible(false); } }}void CCMenuItemSprite::setEnabled(bool bEnabled){ // 如果状态不一样,调用基类方法,并刷新可见性 if( m_bEnabled != bEnabled ) { CCMenuItem::setEnabled(bEnabled); this->updateImagesVisibility(); }}// Helper void CCMenuItemSprite::updateImagesVisibility(){ if (m_bEnabled) // 可用状态,默认一般状态Sprite显示,其他隐藏 { if (m_pNormalImage) m_pNormalImage->setVisible(true); if (m_pSelectedImage) m_pSelectedImage->setVisible(false); if (m_pDisabledImage) m_pDisabledImage->setVisible(false); } else { if (m_pDisabledImage) // 不可用状态,修改仅不可用状态Sprite显示,其他隐藏 { if (m_pNormalImage) m_pNormalImage->setVisible(false); if (m_pSelectedImage) m_pSelectedImage->setVisible(false); if (m_pDisabledImage) m_pDisabledImage->setVisible(true); } else // 选中状态,修改仅选中状态Sprite显示,其他隐藏 { if (m_pNormalImage) m_pNormalImage->setVisible(true); if (m_pSelectedImage) m_pSelectedImage->setVisible(false); if (m_pDisabledImage) m_pDisabledImage->setVisible(false); } }}////// CCMenuItemImage///CCMenuItemImage* CCMenuItemImage::create(){ CCMenuItemImage *pRet = new CCMenuItemImage(); if (pRet && pRet->init()) { pRet->autorelease(); return pRet; } CC_SAFE_DELETE(pRet); return NULL;}bool CCMenuItemImage::init(void){ return initWithNormalImage(NULL, NULL, NULL, NULL, NULL);}CCMenuItemImage * CCMenuItemImage::create(const char *normalImage, const char *selectedImage){ return CCMenuItemImage::create(normalImage, selectedImage, NULL, NULL, NULL);}CCMenuItemImage * CCMenuItemImage::create(const char *normalImage, const char *selectedImage, CCObject* target, SEL_MenuHandler selector){ return CCMenuItemImage::create(normalImage, selectedImage, NULL, target, selector);}CCMenuItemImage * CCMenuItemImage::create(const char *normalImage, const char *selectedImage, const char *disabledImage, CCObject* target, SEL_MenuHandler selector){ CCMenuItemImage *pRet = new CCMenuItemImage(); if (pRet && pRet->initWithNormalImage(normalImage, selectedImage, disabledImage, target, selector)) { pRet->autorelease(); return pRet; } CC_SAFE_DELETE(pRet); return NULL;}CCMenuItemImage * CCMenuItemImage::create(const char *normalImage, const char *selectedImage, const char *disabledImage){ CCMenuItemImage *pRet = new CCMenuItemImage(); if (pRet && pRet->initWithNormalImage(normalImage, selectedImage, disabledImage, NULL, NULL)) { pRet->autorelease(); return pRet; } CC_SAFE_DELETE(pRet); return NULL;}bool CCMenuItemImage::initWithNormalImage(const char *normalImage, const char *selectedImage, const char *disabledImage, CCObject* target, SEL_MenuHandler selector){ // 创建3个Sprite,分别设置成三种不同状态下该显示的图片 CCNode *normalSprite = NULL; CCNode *selectedSprite = NULL; CCNode *disabledSprite = NULL; if (normalImage) { normalSprite = CCSprite::create(normalImage); } if (selectedImage) { selectedSprite = CCSprite::create(selectedImage); } if(disabledImage) { disabledSprite = CCSprite::create(disabledImage); } return initWithNormalSprite(normalSprite, selectedSprite, disabledSprite, target, selector);}//// Setter of sprite frames//void CCMenuItemImage::setNormalSpriteFrame(CCSpriteFrame * frame){ setNormalImage(CCSprite::createWithSpriteFrame(frame));}void CCMenuItemImage::setSelectedSpriteFrame(CCSpriteFrame * frame){ setSelectedImage(CCSprite::createWithSpriteFrame(frame));}void CCMenuItemImage::setDisabledSpriteFrame(CCSpriteFrame * frame){ setDisabledImage(CCSprite::createWithSpriteFrame(frame));}//// MenuItemToggle//void CCMenuItemToggle::setSubItems(CCArray* var){ CC_SAFE_RETAIN(var); CC_SAFE_RELEASE(m_pSubItems); m_pSubItems = var; // 设置轮播数组}CCArray* CCMenuItemToggle::getSubItems(){ return m_pSubItems; // 返回轮播数组}CCMenuItemToggle * CCMenuItemToggle::createWithTarget(CCObject* target, SEL_MenuHandler selector, CCArray* menuItems){ CCMenuItemToggle *pRet = new CCMenuItemToggle(); pRet->CCMenuItem::initWithTarget(target, selector); pRet->m_pSubItems = CCArray::create(); // 创建按默认数组 pRet->m_pSubItems->retain(); for (unsigned int z=0; z < menuItems->count(); z++) { // 添加子菜单项 CCMenuItem* menuItem = (CCMenuItem*)menuItems->objectAtIndex(z); pRet->m_pSubItems->addObject(menuItem); } pRet->m_uSelectedIndex = UINT_MAX; // 将默认的选中项设置为第一个 pRet->setSelectedIndex(0); return pRet;}CCMenuItemToggle * CCMenuItemToggle::createWithTarget(CCObject* target, SEL_MenuHandler selector, CCMenuItem* item, ...){ va_list args; va_start(args, item); CCMenuItemToggle *pRet = new CCMenuItemToggle(); pRet->initWithTarget(target, selector, item, args); pRet->autorelease(); va_end(args); return pRet;}CCMenuItemToggle * CCMenuItemToggle::create(){ CCMenuItemToggle *pRet = new CCMenuItemToggle(); pRet->initWithItem(NULL); pRet->autorelease(); return pRet;}bool CCMenuItemToggle::initWithTarget(CCObject* target, SEL_MenuHandler selector, CCMenuItem* item, va_list args){ CCMenuItem::initWithTarget(target, selector); this->m_pSubItems = CCArray::create(); this->m_pSubItems->retain(); int z = 0; CCMenuItem *i = item; while(i) { z++; m_pSubItems->addObject(i); i = va_arg(args, CCMenuItem*); } m_uSelectedIndex = UINT_MAX; this->setSelectedIndex(0); return true;}CCMenuItemToggle* CCMenuItemToggle::create(CCMenuItem *item){ CCMenuItemToggle *pRet = new CCMenuItemToggle(); pRet->initWithItem(item); pRet->autorelease(); return pRet;}bool CCMenuItemToggle::initWithItem(CCMenuItem *item){ CCMenuItem::initWithTarget(NULL, NULL); setSubItems(CCArray::create()); if (item) { m_pSubItems->addObject(item); } m_uSelectedIndex = UINT_MAX; this->setSelectedIndex(0); setCascadeColorEnabled(true); setCascadeOpacityEnabled(true); return true;}void CCMenuItemToggle::addSubItem(CCMenuItem *item){ m_pSubItems->addObject(item); // 添加一个子菜单项进入轮播数组}CCMenuItemToggle::~CCMenuItemToggle(){ CC_SAFE_RELEASE(m_pSubItems);}void CCMenuItemToggle::setSelectedIndex(unsigned int index){ if( index != m_uSelectedIndex && m_pSubItems->count() > 0 ) // 如果待设置项不等于当前项,且轮播数组大于0 { m_uSelectedIndex = index; // 设置选中项 CCMenuItem *currentItem = (CCMenuItem*)getChildByTag(kCurrentItem); // 获取当前选中项 if( currentItem ) // 如果当前选中项存在 { currentItem->removeFromParentAndCleanup(false); // 从父类中移除但不清空 } CCMenuItem* item = (CCMenuItem*)m_pSubItems->objectAtIndex(m_uSelectedIndex); // 选出轮播数组中对应项 this->addChild(item, 0, kCurrentItem); // 添加至屏幕中 CCSize s = item->getContentSize(); // 获取其大小 this->setContentSize(s); // 重置大小 item->setPosition( ccp( s.width/2, s.height/2 ) ); // 设置坐标 }}unsigned int CCMenuItemToggle::getSelectedIndex(){ return m_uSelectedIndex; // 获取当前选中项}void CCMenuItemToggle::selected(){ CCMenuItem::selected(); // 调用基类方法 ((CCMenuItem*)(m_pSubItems->objectAtIndex(m_uSelectedIndex)))->selected(); // 调用选中项的选中方法}void CCMenuItemToggle::unselected(){ CCMenuItem::unselected(); ((CCMenuItem*)(m_pSubItems->objectAtIndex(m_uSelectedIndex)))->unselected();}void CCMenuItemToggle::activate(){ // update index if( m_bEnabled ) // 如果当前可用 { unsigned int newIndex = (m_uSelectedIndex + 1) % m_pSubItems->count(); this->setSelectedIndex(newIndex); } CCMenuItem::activate();}void CCMenuItemToggle::setEnabled(bool enabled){ if (m_bEnabled != enabled) { CCMenuItem::setEnabled(enabled); if(m_pSubItems && m_pSubItems->count() > 0) { CCObject* pObj = NULL; CCARRAY_FOREACH(m_pSubItems, pObj) { CCMenuItem* pItem = (CCMenuItem*)pObj; pItem->setEnabled(enabled); } } }}CCMenuItem* CCMenuItemToggle::selectedItem(){ return (CCMenuItem*)m_pSubItems->objectAtIndex(m_uSelectedIndex);}由于重复的代码比较多,不少地方也就没有一一注释了,仅在第一次出现时进行了注释。
看完了实现代码我们不难发现,对于Label菜单项的实现,是将Label添加至菜单中,直接对Label进行相应修改以达到目的,而Sprite菜单项的三种状态则对应3个不同的Sprite,在不同状态下仅仅让屏幕上只显示其中一个。
结言
通过这几篇学习笔记我们不难发现,不少控件的实现并不难,只要我们肯想,很多东西我们完全可以自己实现出来,在本次笔记中出现了不少和Label有关的东西,在下一篇笔记中,我们将一起学习。 0 0
- Cocos2d-x学习笔记(十二)CCMenuItem详解
- cocos2d-x学习笔记-CCMenu和CCMenuItem详解
- cocos2d-x学习笔记-CCMenu和CCMenuItem详解
- cocos2d-x学习笔记-CCMenu和CCMenuItem详解
- cocos2d-x学习笔记-CCMenu和CCMenuItem详解
- cocos2d-x学习笔记-CCMenu和CCMenuItem详解
- 我的Cocos2d-x学习笔记(十四)菜单(CCMenu)、菜单项(CCMenuItem)及菜单项子类
- cocos2d-X 节点(CCMenuItem.h)API
- cocos2d-x、CCMenu、CCMenuItem
- 我的Cocos2d-x学习笔记(十二)内存管理
- Cocos2d-x结构学习(十)CCMenu、CCLayerRGBA、CREATE_FUNC、CCMenuItem、tCCMenuState
- cocos2d-x CCMenuItem自动排列
- Cocos2d-x-->CCMenuItem菜单项
- cocos2d-x CCMenuItem菜单项
- Cocos2d-x初入学堂(5)-->CCMenuItem菜单项
- Cocos2d-x学习笔记(十二)-------->x引擎的数据保存
- Cocos2d-x学习笔记(十二)—— Box2d物理引擎(未完)
- cocos2d-x 菜鸟学习笔记十二(粒子系统的研究初接触)
- Project Euler 7
- hdu 2817 A sequence of numbers (快速幂)
- error C1189: #error : MFC does not support
- 离开老公看到就算了开工建设克里夫冠军联赛监理公司
- Regular Expression Matching
- Cocos2d-x学习笔记(十二)CCMenuItem详解
- queue相关操作
- VC6.0打开文件以及向工程中添加文件时程序崩溃自动退出
- Cocos2d-x学习笔记(十三)CCLabel详解
- Linux 内核开发 - 内核定时器
- 《Effective C++》学习笔记(七)
- priority_queue相关操作
- hibernate对象关系映射(基于注解)
- CF 463D Gargari and Permutations (dp)