本篇博客出自阿修罗道,转载请注明出处:http://blog.csdn.net/fansongy/article/details/12795299
上篇说到将CocoStudio的导出文件在程序中运行出来,但是并没有用户交互,即点击响应,程序的逻辑判断也都没有。这篇中我们把它们加进去,这样就可以算一个完整的程序了。先上个图:
运行后,点击开始,进度条,数字增加,通过slider可以调整进度条增长的速度。
大部分界面编辑都在CocoStudio中完成,怎么编辑可以参照:
现在我们要做的工作是将所需要交互控件的Tag记下来,这样我们可以通过Tag找到这个控件。
将Tag整理后我将其记录到一个.h文件中这样在工程中就可以使用了:
const int UI_BUTTON_CLEAR = 8; const int UI_BUTTON_START = 9; const int UI_SLIDER_SPEED = 10; const int UI_LOADINGBAR_LOADING = 3; const int UI_LABELATLAS_LIFENUM = 7;
由于此处tag是CocoStudio自己生成的,所以跟大家自己可能不一样,要根据自己的进行更改。
记录好之后导出文件到我们的工程中。
关联的核心在于设置响应函数、读取与改变控件状态。
首先,我在init中将Layout读入,存储为类的成员变量m_layout。不太会弄的同学可参考上一篇博客。
按钮是要有响应函数的,由于它是UIWidget的一个子类,所以采用的是TouchEvent的回调方式,看不太明白的同学可以参考:
//定义
void touchButton(Object* obj, TouchEventType eventType); //挂载 Button* startBtn = dynamic_cast<Button*>(m_layout->getChildByTag(UI_BUTTON_START)); startBtn->addTouchEventListener(this,toucheventselector(HelloWorld::touchButton)); Button* pauseBtn = dynamic_cast<Button*>(m_layout->getChildByTag(UI_BUTTON_CLEAR)); pauseBtn->addTouchEventListener(this,toucheventselector(HelloWorld::touchButton));
// 实现 void HelloWorld::touchButton(Object* obj, gui::TouchEventType eventType) { auto button = dynamic_cast<Button*>(obj); int tag = button->getTag(); switch(eventType) { case TouchEventType::TOUCH_EVENT_ENDED: if(tag == UI_BUTTON_START) { changeRunning(); } else { clearRunning(); } } }
值得注意的是这个场景中有两个按钮,我们可以采用Tag来进行区分。
对于进度条和数字,我们需要做的是读取它的状态,并对它进行改变。在这个例子中我们需要在schedule的回调函数中做。Schedule的相关知识比较简单,此处不做讨论,有兴趣的同学可查阅其他资料。
void HelloWorld::runningSchedule(float dt) { int speed = dynamic_cast<Slider*>(m_layout->getChildByTag(UI_SLIDER_SPEED))->getPercent(); auto loadingBar = dynamic_cast<LoadingBar*>(m_layout->getChildByTag(UI_LOADINGBAR_LOADING)); int prc = loadingBar->getPercent() + speed / 15; if(prc > 100) { prc = 1; } loadingBar->setPercent(prc); auto numLabel = dynamic_cast<TextAtlas*>(m_layout->getChildByTag(UI_LABELATLAS_LIFENUM)); int num = atoi(numLabel->getStringValue().c_str()); num++; char buff[100]; sprintf_s(buff,"%d",num); numLabel->setStringValue(buff); } void HelloWorld::clearRunning() { if(m_isRunning) { changeRunning(); } dynamic_cast<TextAtlas*>(m_layout->getChildByTag(UI_LABELATLAS_LIFENUM))->setStringValue("1"); dynamic_cast<LoadingBar*>(m_layout->getChildByTag(UI_LOADINGBAR_LOADING))->setPercent(1); dynamic_cast<Slider*>(m_layout->getChildByTag(UI_SLIDER_SPEED))->setPercent(1); } void HelloWorld::changeRunning() { if(m_isRunning) { //pause this->unschedule(schedule_selector(HelloWorld::runningSchedule)); m_isRunning = false; Button* button = dynamic_cast<Button*>(m_layout->getChildByTag(UI_BUTTON_START)); button->setTitleText("运行"); } else { //start this->schedule(schedule_selector(HelloWorld::runningSchedule)); m_isRunning = true; Button* button = dynamic_cast<Button*>(m_layout->getChildByTag(UI_BUTTON_START)); button->setTitleText("暂停"); } }
编译运行,即可看到效果啦。
通过建立一个Tag的索引表来找到UI中的控件资源,然后取到对其进行操作。这其中可能会有的问题是,如果多个UI控件被加载Tag可能会重复,大家要注意这点。希望cocoStudio在未来的版本中能够将Tag索引表导出成资源的.h文件。
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "CocosGUI.h" #include "cocostudio/CocoStudio.h" using namespace cocos2d; // cocos2d-x 3.0 不建议使用 [USING_NS_CC;] using namespace gui; using namespace cocostudio; class HelloWorld : public cocos2d::Layer { public: // there's no 'id' in cpp, so we recommend returning the class instance pointer static cocos2d::Scene* createScene(); // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // a selector callback void menuCloseCallback(Object* pSender); // implement the "static create()" method manually CREATE_FUNC(HelloWorld); HelloWorld(); void touchButton(Object* obj, cocos2d::gui::TouchEventType eventType); void runningSchedule(float dt); private: void clearRunning(); void changeRunning(); void changeSpeed(int speed); bool m_isRunning; Layout* m_layout; }; #endif // __HELLOWORLD_SCENE_H__
#include "HelloWorldScene.h" const int UI_BUTTON_CLEAR = 11; const int UI_BUTTON_START = 10; const int UI_SLIDER_SPEED = 9; const int UI_LOADINGBAR_LOADING = 6; const int UI_LABELATLAS_LIFENUM = 5; //! convert from wstring to UTF8 using self-coding-converting void WStrToUTF8(std::string& dest, const std::wstring& src){ dest.clear(); for (size_t i = 0; i < src.size(); i++){ wchar_t w = src[i]; if (w <= 0x7f) dest.push_back((char)w); else if (w <= 0x7ff) { dest.push_back(0xc0 | ((w >> 6)& 0x1f)); dest.push_back(0x80| (w & 0x3f)); } else if (w <= 0xffff) { dest.push_back(0xe0 | ((w >> 12)& 0x0f)); dest.push_back(0x80| ((w >> 6) & 0x3f)); dest.push_back(0x80| (w & 0x3f)); } else if (sizeof(wchar_t) > 2 && w <= 0x10ffff) { dest.push_back(0xf0 | ((w >> 18)& 0x07)); // wchar_t 4-bytes situation dest.push_back(0x80| ((w >> 12) & 0x3f)); dest.push_back(0x80| ((w >> 6) & 0x3f)); dest.push_back(0x80| (w & 0x3f)); } else dest.push_back('?'); } } //! simple warpper std::string WStrToUTF8(const std::wstring& str) { std::string result; WStrToUTF8(result, str); return result; } HelloWorld::HelloWorld(): m_isRunning(false) { } Scene* HelloWorld::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Point origin = Director::getInstance()->getVisibleOrigin(); ///////////////////////////// // 2. add a menu item with "X" image, which is clicked to quit the program // you may modify it. // add a "close" icon to exit the progress. it's an autorelease object auto closeItem = MenuItemImage::create( "CloseNormal.png", "CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); closeItem->setPosition(Point(origin.x + visibleSize.width - closeItem->getContentSize().width/2 , origin.y + closeItem->getContentSize().height/2)); // create menu, it's an autorelease object auto menu = Menu::create(closeItem, NULL); menu->setPosition(Point::ZERO); this->addChild(menu, 1); ///////////////////////////// // 3. add your codes below... // add a label shows "Hello World" // create and initialize a label // cocos2d-x 3.0 beta Layer * layer = Layer::create(); m_layout = dynamic_cast<Layout*>(cocostudio::GUIReader::getInstance()->widgetFromJsonFile("testUI\\testUI.ExportJson")); // myLayout->setPosition(Point(origin.x + visibleSize.width/2 - myLayout->getContentSize().width/2, // origin.y + visibleSize.height/2 - myLayout->getContentSize().height/2)); layer->addChild(m_layout); this->addChild(layer); ////////// 获取数字标签 /////////////// TextAtlas* labelNum = dynamic_cast<TextAtlas*>(m_layout->getChildByTag(UI_LABELATLAS_LIFENUM)); labelNum->setStringValue("1"); ////////// 获取开始按钮 /////////////// Button* startBtn = dynamic_cast<Button*>(m_layout->getChildByTag(UI_BUTTON_START)); startBtn->addTouchEventListener(this,toucheventselector(HelloWorld::touchButton)); ////////// 获取清除按钮 /////////////// Button * clearBtn = dynamic_cast<Button*>(m_layout->getChildByTag(UI_BUTTON_CLEAR)); clearBtn->addTouchEventListener(this, toucheventselector(HelloWorld::touchButton)); return true; } void HelloWorld::touchButton(Object* obj, gui::TouchEventType eventType) { auto button = dynamic_cast<Button*>(obj); int tag = button->getTag(); switch(eventType) { case TouchEventType::TOUCH_EVENT_ENDED: if(tag == UI_BUTTON_START) { changeRunning(); } else { clearRunning(); } } } void HelloWorld::clearRunning() { if(m_isRunning) { changeRunning(); } dynamic_cast<TextAtlas*>(m_layout->getChildByTag(UI_LABELATLAS_LIFENUM))->setStringValue("1"); dynamic_cast<LoadingBar*>(m_layout->getChildByTag(UI_LOADINGBAR_LOADING))->setPercent(1); dynamic_cast<Slider*>(m_layout->getChildByTag(UI_SLIDER_SPEED))->setPercent(1); } void HelloWorld::changeRunning() { if(m_isRunning) { //pause this->unschedule(schedule_selector(HelloWorld::runningSchedule)); m_isRunning = false; Button* button = dynamic_cast<Button*>(m_layout->getChildByTag(UI_BUTTON_START)); button->setTitleText(WStrToUTF8(L"运行")); } else { //start this->schedule(schedule_selector(HelloWorld::runningSchedule)); m_isRunning = true; Button* button = dynamic_cast<Button*>(m_layout->getChildByTag(UI_BUTTON_START)); button->setTitleText(WStrToUTF8(L"暂停")); } } void HelloWorld::runningSchedule(float dt) { int speed = dynamic_cast<Slider*>(m_layout->getChildByTag(UI_SLIDER_SPEED))->getPercent(); auto loadingBar = dynamic_cast<LoadingBar*>(m_layout->getChildByTag(UI_LOADINGBAR_LOADING)); int prc = loadingBar->getPercent() + speed / 15; if(prc > 100) { prc = 1; } loadingBar->setPercent(prc); auto numLabel = dynamic_cast<TextAtlas*>(m_layout->getChildByTag(UI_LABELATLAS_LIFENUM)); int num = atoi(numLabel->getStringValue().c_str()); num++; char buff[100]; sprintf_s(buff,"%d",num); numLabel->setStringValue(buff); } void HelloWorld::menuCloseCallback(Object* pSender) { Director::getInstance()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) exit(0); #endif }