cocos2d-x 模态对话框的实现

心情不好,恩,不扯淡了,直接讲。

==================================

在泰然看了一篇实现模态对话框的文章,写的还不错,然后在其基础上加了我简单加了一层灰色透明背景,这样子界面效果看起来会更友好一点,好吧,原谅我的无耻,原创转载什么的也不在意了,原文在这里,今天感觉有点累,恩,主要是大神不能带我飞了,很是失落,好吧,不说废话了。

在游戏中,我们常常需要实现弹出一个模态对话框,比如说游戏暂停,退出提示对话框等

对话框特点如下:

1.可定制的,比如说背景图,标题,文本,按钮等,根据需要添加和设置

2.需要屏蔽对话框下层的触摸

3.为了友好的效果显示,把不可触摸的部分变为灰色

先来看一张效果图:

为了完成这样一个效果,思路如下:

1.设计一个弹出对话框的类PopupLayer,继承于LayerColor,这样子我们就可以设置背景版透明,看起来好像把对话框下层的变灰暗了

        setColor(ccc3(0,0,0));
        setOpacity(128);  

2.添加触摸事件,屏蔽下层触摸,也就是在Layer中设置不向下传递

        //add layer touch event
	auto listener = EventListenerTouchOneByOne::create();
	listener->setSwallowTouches(true);//不向下传递触摸
	listener->onTouchBegan = CC_CALLBACK_2(PopupLayer::onTouchBegan, this);
	listener->onTouchMoved = CC_CALLBACK_2(PopupLayer::onTouchMoved, this);
	listener->onTouchEnded = CC_CALLBACK_2(PopupLayer::onTouchEnded, this);
	auto dispatcher = Director::getInstance()->getEventDispatcher();
	dispatcher->addEventListenerWithSceneGraphPriority(listener, this);

3.PopupLayer类 实现 可定制对话框标题,按钮,文本,背景图片等

    //标题
    void setTitle(const char* title, int fontsize = 20);
    //文本
    void setContentText(const char* text, int fontsize = 20, int padding = 50, int paddintTop = 100);
    //设置button回调事件
    void setCallbackFunc(Ref* target, SEL_CallFuncN callfun);
     //添加button
    bool addButton(const char* normalImage, const char* selectedImage, const char* title, int tag = 0);

4.按钮回调函数实现也比较简单,首先设置外部的回调对象和回调函数

    Ref* m_callbackListener;    //回调对象
    SEL_CallFuncN m_callback;   //回调函数

    //设置按钮的回调函数
    void PopupLayer::setCallbackFunc(Ref* target, SEL_CallFuncN callfun){
    m_callbackListener = target;
    m_callback = callfun;
    }

然后在PopupLayer类中比如说我们添加一个菜单按钮

 // 创建图片菜单按钮
    auto item = MenuItemImage::create(
        normalImage,
        selectedImage,
        CC_CALLBACK_1(PopupLayer::buttonCallBack,this));
    item->setTag(tag);

设置button回调函数,然后由这个回调函数去调用外部的button监听函数,然后关闭对话框

//button回调函数
    void PopupLayer::buttonCallBack(Ref* pSender){
    Node* node = dynamic_cast<Node*>(pSender);
    CCLog("【====PopupLayer::buttonCallBack====】touch tag: %d", node->getTag());
    if (m_callback && m_callbackListener){
        (m_callbackListener->*m_callback)(node);
    }
    this->removeFromParent();}

5.然后用法也比较简单,如果需要对话框内容显示中文,可以参考:cocos2d-x
3.0 使用Sax解析xml文档(解决中文显示问题)
这篇文章

    //弹出对话框
    pl = PopupLayer::create("BackGround.png",Size(400,350));
    pl->setTitle("title");
    pl->setContentText("Are you sure exit?", 20, 60, 250);
    pl->setCallbackFunc(this, callfuncN_selector(WelcomeScene::popButtonCallback));//设置按钮回调
    pl->addButton("pop_button.png", "pop_button.png", "yes", 0);
    pl->addButton("pop_button.png", "pop_button.png", "no", 1);
    this->addChild(pl);

外部回调函数实现,根据tag判断点了什么按钮

void WelcomeScene::popButtonCallback(Node *pNode){
    CCLog("【=====WelcomeScene::popButtonCallback======】button call back. tag: %d", pNode->getTag());
    //exit
    if(pNode->getTag() == 0){
        Director::getInstance()->end();
    }
}

恩,思路大概这样子,完整的对话框类如下,亲们可以复制直接使用

#pragma once

#include "cocos2d.h"
#include "cocos-ext.h"

using namespace cocos2d;
using namespace cocos2d::extension;

class PopupLayer : public LayerColor{
public:
	PopupLayer();
	~PopupLayer();

	virtual bool init();
	CREATE_FUNC(PopupLayer);
	static PopupLayer* create(const char* backgroundImage,Size dialogSize);

	//touch事件监听 屏蔽向下触摸
	bool onTouchBegan(Touch *touch, Event *event);
	void onTouchMoved(Touch *touch, Event *event);
	void onTouchEnded(Touch* touch, Event* event);

	//标题
	void setTitle(const char* title, int fontsize = 20);
	//文本
	void setContentText(const char* text, int fontsize = 20, int padding = 50, int paddintTop = 100);
	//设置button回调事件
	void setCallbackFunc(Ref* target, SEL_CallFuncN callfun);
	//添加button
	bool addButton(const char* normalImage, const char* selectedImage, const char* title, int tag = 0);

	virtual void onEnter();
	virtual void onExit();

	void backgroundFinish();

private:

	void buttonCallBack(Ref* pSender);

	// 文字内容两边的空白区
	int m_contentPadding;
	int m_contentPaddingTop;

	Size m_dialogContentSize;

	Ref* m_callbackListener;
	SEL_CallFuncN m_callback;

	//set and get
	CC_SYNTHESIZE_RETAIN(Menu*, m__pMenu, MenuButton);
	CC_SYNTHESIZE_RETAIN(Sprite*, m__sfBackGround, SpriteBackGround);
	CC_SYNTHESIZE_RETAIN(Scale9Sprite*, m__s9BackGround, Sprite9BackGround);
	CC_SYNTHESIZE_RETAIN(LabelTTF*, m__ltTitle, LabelTitle);
	CC_SYNTHESIZE_RETAIN(LabelTTF*, m__ltContentText, LabelContentText);
};

cpp文件实现如下:

#include "PopupLayer.h"

PopupLayer::PopupLayer():
	m__pMenu(NULL)
	, m_contentPadding(0)
	, m_contentPaddingTop(0)
	, m_callbackListener(NULL)
	, m_callback(NULL)
	, m__sfBackGround(NULL)
	, m__s9BackGround(NULL)
	, m__ltContentText(NULL)
	, m__ltTitle(NULL)
{

}

PopupLayer::~PopupLayer(){
	CC_SAFE_RELEASE(m__pMenu);
	CC_SAFE_RELEASE(m__sfBackGround);
	CC_SAFE_RELEASE(m__ltContentText);
	CC_SAFE_RELEASE(m__ltTitle);
	CC_SAFE_RELEASE(m__s9BackGround);
}

bool PopupLayer::init(){
	if(!LayerColor::init()){
		return false;
	}
	// 初始化需要的 Menu
	Menu* menu = Menu::create();
	menu->setPosition(CCPointZero);
	setMenuButton(menu);

	//add layer touch event
	auto listener = EventListenerTouchOneByOne::create();
	listener->setSwallowTouches(true);
	listener->onTouchBegan = CC_CALLBACK_2(PopupLayer::onTouchBegan, this);
	listener->onTouchMoved = CC_CALLBACK_2(PopupLayer::onTouchMoved, this);
	listener->onTouchEnded = CC_CALLBACK_2(PopupLayer::onTouchEnded, this);
	auto dispatcher = Director::getInstance()->getEventDispatcher();
	dispatcher->addEventListenerWithSceneGraphPriority(listener, this);

	setColor(ccc3(0,0,0));
	setOpacity(128);  

	return true;
}

bool PopupLayer::onTouchBegan(Touch *touch, Event *event){
	return true;
}

void PopupLayer::onTouchMoved(Touch *touch, Event *event){

}

void PopupLayer::onTouchEnded(Touch* touch, Event* event){

}

PopupLayer* PopupLayer::create(const char* backgroundImage, Size dialogSize){

	PopupLayer* layer = PopupLayer::create();

//	layer->setSpriteBackGround(Sprite::create(backgroundImage));
	layer->setSprite9BackGround(Scale9Sprite::create(backgroundImage));

	layer->m_dialogContentSize = dialogSize;

	return layer;
}

void PopupLayer::setTitle(const char* title, int fontsize /* = 20 */){
	LabelTTF* label = LabelTTF::create(title,"",fontsize);
	setLabelTitle(label);
}

void PopupLayer::setContentText(const char *text, int fontsize, int padding, int paddingTop){
	LabelTTF* ltf = LabelTTF::create(text, "", fontsize);
	setLabelContentText(ltf);
	m_contentPadding = padding;
	m_contentPaddingTop = paddingTop;
}

void PopupLayer::setCallbackFunc(Ref* target, SEL_CallFuncN callfun){
	m_callbackListener = target;
	m_callback = callfun;
}

bool PopupLayer::addButton(const char* normalImage, const char* selectedImage, const char* title, int tag /* = 0 */){

	auto size = Director::getInstance()->getWinSize();
	auto center = Point(size.width / 2, size.height / 2);

	// 创建图片菜单按钮
	auto item = MenuItemImage::create(
		normalImage,
		selectedImage,
		CC_CALLBACK_1(PopupLayer::buttonCallBack,this));
	item->setTag(tag);
	item->setPosition(center);

	// 添加文字说明并设置位置
	Size itemSize = item->getContentSize();
	LabelTTF* ttf = LabelTTF::create(title, "", 20);
	ttf->setColor(Color3B(0, 0, 0));
	ttf->setPosition(Point(itemSize.width / 2, itemSize.height / 2));
	item->addChild(ttf);

	getMenuButton()->addChild(item);

	return true;
}

void PopupLayer::buttonCallBack(Ref* pSender){
	Node* node = dynamic_cast<Node*>(pSender);
	CCLog("【====PopupLayer::buttonCallBack====】touch tag: %d", node->getTag());
	if (m_callback && m_callbackListener){
		(m_callbackListener->*m_callback)(node);
	}
	this->removeFromParent();
}

void PopupLayer::onEnter(){
	LayerColor::onEnter();

	Size winSize = CCDirector::getInstance()->getWinSize();
	Point pCenter = Point(winSize.width / 2, winSize.height / 2);

//	Size contentSize ;
	// 设定好参数,在运行时加载
	//如果没有设置 ContentSize ,那么采取的方案是,窗口大小与传入图片一样大
// 	if (getContentSize().equals(this->getParent()->getContentSize())) {
// 		getSpriteBackGround()->setPosition(ccp(winSize.width / 2, winSize.height / 2));
// 		this->addChild(getSpriteBackGround(), 0, 0);
// 		contentSize = getSpriteBackGround()->getTexture()->getContentSize();
// 	} else {
// 		Scale9Sprite *background = getSprite9BackGround();
// 		background->setContentSize(getContentSize());
// 		background->setPosition(ccp(winSize.width / 2, winSize.height / 2));
// 		this->addChild(background, 0, 0);
// 		contentSize = getContentSize();
// 	}
	//添加背景图片
	Scale9Sprite *background = getSprite9BackGround();
	background->setContentSize(m_dialogContentSize);
	background->setPosition(Point(winSize.width / 2, winSize.height / 2));
	this->addChild(background,0,0);

	// 弹出效果
	Action* popupLayer = Sequence::create(
		ScaleTo::create(0.0, 0.0),
		ScaleTo::create(0.2, 1.05),
		ScaleTo::create(0.2, 0.95),
		ScaleTo::create(0.1, 1.0),
		CallFunc::create(CC_CALLBACK_0(PopupLayer::backgroundFinish,this)),
		NULL
		);
	background->runAction(popupLayer);

}

void PopupLayer::backgroundFinish(){

	Size winSize = CCDirector::getInstance()->getWinSize();
	Point pCenter = Point(winSize.width / 2, winSize.height / 2);

	// 添加按钮,并设置其位置
	this->addChild(getMenuButton());
	float btnWidth = m_dialogContentSize.width / (getMenuButton()->getChildrenCount() + 1);

	Vector<Node*> vector = getMenuButton()->getChildren();
	Ref* pObj = NULL;
	int i = 0;
	for(Node* pObj : vector){
		Node* node = dynamic_cast<Node*>(pObj);
		node->setPosition(Point( winSize.width / 2 - m_dialogContentSize.width / 2 + btnWidth * (i + 1), winSize.height / 2 - m_dialogContentSize.height / 3));
		i++;
	}

	// 显示对话框标题
	if (getLabelTitle()){
		getLabelTitle()->setPosition(ccpAdd(pCenter, ccp(0, m_dialogContentSize.height / 2 - 35.0f)));
		this->addChild(getLabelTitle());
	}

	// 显示文本内容
	if (getLabelContentText()){
		CCLabelTTF* ltf = getLabelContentText();
		ltf->setPosition(ccp(winSize.width / 2, winSize.height / 2));
		ltf->setDimensions(CCSizeMake(m_dialogContentSize.width - m_contentPadding * 2, m_dialogContentSize.height - m_contentPaddingTop));
		ltf->setHorizontalAlignment(kCCTextAlignmentLeft);
		this->addChild(ltf);
	}
}

void PopupLayer::onExit(){

	CCLog("popup on exit.");
	CCLayerColor::onExit();
}

cocos2d-x 模态对话框的实现

时间: 2024-11-19 01:29:36

cocos2d-x 模态对话框的实现的相关文章

QT笔记之模态对话框及非模态对话框

模态对话框(Modal Dialog)与非模态对话框(Modeless Dialog)的概念不是Qt所独有的,在各种不同的平台下都存在.又有叫法是称为模式对话框,无模式对话框等.所谓模态对话框就是在其没有被关闭之前,用户不能与同一个应用程序的其他窗口进行交互,直到该对话框关闭.对于非模态对话框,当被打开时,用户既可选择和该对话框进行交互,也可以选择同应用程序的其他窗口交互. 在Qt中,显示一个对话框一般有两种方式,一种是使用exec()方法,它总是以模态来显示对话框:另一种是使用show()方法

JavaScript内容梳理 示例之模态对话框 示例之全选和反选以及取消 示例之后台管理左侧菜单

1 <!DOCTYPE html> 2 <!--示例之模态对话框--> 3 <html lang="en"> 4 <head> 5 <meta charset="UTF-8"> 6 <title>Title</title> 7 <style> 8 .hide{ 9 display: none; 10 } 11 .c1{ 12 position: fixed; 13 lef

bootstrap添加多个模态对话框支持

bootstrap添加多个模态对话框支持 (2015-03-04 21:05:35) 转载▼ 标签: 房产   因为项目需要,在页面交互上要弹出多个dialog窗口,而bootstrap的modal支持弹出dialog窗口,但是如果在此基础上,会出现遮罩层越来越多,背景越来越黑的情况. 代码具体如下: (function(){ modal = {}; modal.openDialog = function(url, title, width, height, id){}; modal.close

QT模态对话框用法(在UI文件中设置Widget背景图,这个图是一个带阴影边框的图片——酷)

QT弹出模态对话框做法: 1.新建UI文件时,一定要选择基类是QDialog的,我的选择是:Dialog without Buttons(),如下图: 2.然后在使用的时候: MyDialog dlg(this); dlg.exec(); 如果不加this,则会在任务管理器里面产生一个新的EXE. 3.如果对话框的标题是自定义,不想使用系统的标题,这时候需要在代码中加入: setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint ); setAttr

QDialog 模态对话框与事件循环

起源 qtcn中文论坛中有网友问到: 假设程序正常运行时,只有一个简单的窗体A,此时只有一个GUI主线程,在这个主线程中有一个事件循环处理窗体上的事件.当此程序运行到某阶段时,弹出一个模态窗体B(书上说模态窗体是有其自己的事件循环的),此时模态窗体B是否会有一个对应的子线程处理其事件循环? 这儿其实有两个问题: 模态对话框 和 事件循环 没有必然联系 事件循环 和 子线程 没有必然联系 题外: 如果进一步呢?其实我们还可以说: 模态对话框 和 QDialog 没必要联系 QDialog 对话框

大三在校生的传智120天的1200小时.net(十四) 关于easyUI的模态对话框

会用easyUI的模态对话框会是我们的开发更加简洁,只需下载这个插件,把需要的文件拖到项目中,下面展示一个easyUI的模态对话框,以及使用方法和属性.这里是一个常用功能小展示,试试上easyUI自带的说明文档非常全面,*****学会查看文档很重要,看几次就会熟练***** <script type="text/javascript" src="../Script/jquery-1.8.3.js"></script> <script s

MFC中模态对话框和非模态对话框

MFC的对话框非为两种,一种叫模态对话框(Modal  Dialog  Box,又叫做模式对话框),一种叫做非模式对话框(Modaless Dialog Box,又叫无模式对话框).两者的区别在于当对话框打开的时候,是否允许用户进行其他对象的操作. 一.模态对话框 模态对话框指,当用户需要对该对话框之外的其他对话框或者模块进行操作时,必须该对话框关闭,才能去编辑其他对话框或者模块. 创建如下: //创建模态对话框 CModalDialog modalDialog; modalDialog.DoM

Qt的模态对话框和非模态对话框 经常使用setAttribute (Qt::WA_DeleteOnClose)

模态对话框就是指在子对话框弹出时,焦点被强行集中于该子对话框,子对话框不关闭,用户将无法操作其他的窗口.非模态相反,用户仍然可以操作其他的窗口,包括该子对话框的父对话框. 如果从线程角度来讲,模态对话框实际上是线程阻塞的,也就是子对话框是一个线程,但是在创建这个子线程之后,父窗口就阻塞了:模态对话框则不是阻塞型的线程模型,父子线程可以并行运行. 和所有流行的图形类库一样,Qt也提供了创建模态和非模态对话框的机制. 在Qt中创建模态对话框,主要用到了QDialog的exec函数: SonDialo

MFC模态与非模态对话框

1.简述 1.1模态对话框(model dialog box) 当模态对话框显示时,程序会暂停执行,直到关闭这个模态对话框之后,才能执行程序中的其他任务. 1.2非模态对话框(modeless dialog box) 当非模态对话框显示时,运行转而执行程序中的其他任务,而不用关闭这个对话框. 2.代码 2.1模态对话框的实现 void CModelCtrDlg::OnBnClickedButton1() { // TODO: 在此添加控件通知处理程序代码 TestDialog1 dlg; dlg