[cocos2dx笔记010]用于UI的事件管理器

cocos2dx有一个编辑器:cocostudio,目前来说,已经是比较好用了,只要加载导出的资源,就可以用上了。省去手动搭建面的麻烦。但是,很多需要事件的地方,操作比较麻烦,所以这里提供一个事件管理器来集中和简化管理事件。对于C++事件委托方面,我这里使用了是FastDelegate(注:一个牛人写的)。下面是具体实现的代理,不多。

/*
	UI触摸事件管理器。
	原有cocos2dx带的触摸事件,每次监听要操作的步骤比较多,为此增加了一个事件管理器,来集中和简化管理
*/
#ifndef _X_TOUCH_EVENT_MANAGER_H_
#define _X_TOUCH_EVENT_MANAGER_H_
#include <cocos2d.h>
#include <cocos-ext.h>
#include <FastDelegate.h>
#include <xmap.h>
#include <xlog.h>
namespace zdh
{
	USING_NS_CC;
	USING_NS_CC_EXT;
	class XTouchEventManager : public CCObject
	{
	public:
		//绑定的事件定义
		typedef fastdelegate::FastDelegate<void(gui::Widget *, gui::TouchEventType)> TTouchEvent;

		typedef int TagID_t;
		//一个Tag的触模事件结构,包括了四个事件
		struct STagEvent
		{
			TTouchEvent EventBegin;
			TTouchEvent EventMoved;
			TTouchEvent EventEnded;
			TTouchEvent EventCanceled;

			TTouchEvent * getByType(gui::TouchEventType paramType)
			{
				switch (paramType)
				{
				case gui::TOUCH_EVENT_BEGAN:
					return &EventBegin;
				case gui::TOUCH_EVENT_MOVED:
					return &EventMoved;
				case gui::TOUCH_EVENT_ENDED:
					return &EventEnded;
				case gui::TOUCH_EVENT_CANCELED:
					return &EventCanceled;
				}
				return nullptr;
			}
			//判断事件是不是都是为空
			bool isAllEmpty() const
			{
				return EventBegin.empty()
					&& EventEnded.empty()
					&& EventMoved.empty()
					&& EventCanceled.empty();
			}
		};
		//Tag事件映射表,可以换用std::map
		typedef XMap<TagID_t, STagEvent> TEventMap;
	public:
		XTouchEventManager()
			:m_UI(nullptr)
		{}

		static XTouchEventManager * create()
		{
			XTouchEventManager * pRet = new XTouchEventManager();
			pRet->autorelease();
			return pRet;
		}
		//property
		void setUI(gui::TouchGroup * paramUI)
		{
			m_UI = paramUI;
		}
		gui::TouchGroup * getUI()
		{
			return m_UI;
		}
		//绑定一个指定Tag和事件类型的事件
		TTouchEvent * Bind(TagID_t paramTagID, gui::TouchEventType paramType)
		{
			if (!(paramType == gui::TOUCH_EVENT_BEGAN
				|| paramType == gui::TOUCH_EVENT_CANCELED
				|| paramType == gui::TOUCH_EVENT_ENDED
				|| paramType == gui::TOUCH_EVENT_MOVED))  return nullptr;

			int iIndex = m_Map.getIndexBykey(paramTagID);
			if (m_Map.isValidIndex(iIndex))
			{
				return m_Map.getValue(iIndex).getByType(paramType);
			}
			else
			{
				gui::Widget * pWidget = GetNodeByTag(paramTagID);
				if (isNULL(pWidget)) return nullptr;
				pWidget->addTouchEventListener(this, gui::SEL_TouchEvent(&XTouchEventManager::OnUITouch));
				return m_Map[paramTagID].getByType(paramType);
			}
		}

		//移除指定Tag和事件类型的侦听
		void RemoveListen(TagID_t paramTagID, gui::TouchEventType paramType)
		{
			if (!(paramType == gui::TOUCH_EVENT_BEGAN
				|| paramType == gui::TOUCH_EVENT_CANCELED
				|| paramType == gui::TOUCH_EVENT_ENDED
				|| paramType == gui::TOUCH_EVENT_MOVED))  return;
			int iIndex = m_Map.getIndexBykey(paramTagID);
			if (m_Map.isValidIndex(iIndex))
			{
				auto pV = m_Map.getValue(iIndex);
				pV.getByType(paramType)->clear();
				if (pV.isAllEmpty())  //如果这个Tag完全没有事件侦听,那么就清除这个Tag的侦听
				{
					RemoveListen(paramTagID);
				}
			}
		}
		//移除指定Tag的侦听
		void RemoveListen(TagID_t paramTagID)
		{
			gui::Widget * pWidget = GetNodeByTag(paramTagID);
			if (isNotNULL(pWidget))
			{
				pWidget->addTouchEventListener(nullptr, nullptr);
			}
			m_Map.RemoveByKey(paramTagID);
		}

	private:
		//当UI被侦听的事件,被触发
		void OnUITouch(CCObject* paramSender, gui::TouchEventType paramType)
		{
			gui::Widget * pUIControl = dynamic_cast<gui::Widget *>(paramSender);
			if (isNULL(pUIControl)) return;

			TagID_t tagID = pUIControl->getTag();
			STREAM_INFO << "Sender Tag=" << tagID << ", paramType=" << paramType;

			int iIndex = m_Map.getIndexBykey(tagID);
			if (m_Map.isValidIndex(iIndex))
			{
				auto pV = m_Map.getValue(iIndex);
				auto pEvent = pV.getByType(paramType);
				if (isNotNULL(pEvent) && (!pEvent->empty()))
				{
					(*pEvent)(pUIControl, paramType); //调用事件
				}
			}
		}
		//取UI中指定Tag的widget对象
		gui::Widget * GetNodeByTag(TagID_t paramTag)
		{
			if (isNULL(m_UI)) return nullptr;
			return m_UI->getWidgetByTag(paramTag);
		}

	private:
		gui::TouchGroup * m_UI;		//用Cocostudio UI编辑器,然后导入生成的UI对象
		TEventMap m_Map;			//事件侦听映射表
	};
}
#endif

使用例子:在Init函数

		m_EventManager = XTouchEventManager::create();
		m_EventManager->retain();

		gui::TouchGroup* ul = gui::TouchGroup::create();
		ul->addWidget(GUIReader::shareReader()->widgetFromJsonFile("MainUI_1.ExportJson"));
		this->addChild(ul, 2);

		m_EventManager->setUI(m_MainUI);

最后,事件绑定:

		m_EventManager->Bind(ET_BUTTON_EXIT, gui::TOUCH_EVENT_ENDED)->bind(this, &XSceneMain::OnExit);
		m_EventManager->Bind(ET_BUTTON_SAVE, gui::TOUCH_EVENT_ENDED)->bind(this, &XSceneMain::OnSave);

事件的定义:

	void XSceneMain::OnExit(gui::Widget * paramSender, gui::TouchEventType paramType)
	{
		STREAM_INFO << "OnExit";
	}
        void XSceneMain::OnSave(gui::Widget * paramSender, gui::TouchEventType paramType)
	{
		STREAM_INFO << "OnSave";
	}

依赖的代码参考:我的开发代码

[cocos2dx笔记010]用于UI的事件管理器

时间: 2024-08-28 21:56:21

[cocos2dx笔记010]用于UI的事件管理器的相关文章

自定义的事件管理器

自定义的事件管理器 周银辉 大多数框架下都提供了事件管理器的,但不使用框架时为了让事件发送者和事件接收者之间解耦,就可以如下写个简单的 public enum EventAdministratorEventTypes { ApplicationStartup, //在这里添加你需要的事件 } public class EventAdministratorEventArgs : EventArgs { public object Arg { get; protected set; } public

事件管理器

项目开发过程中经常会用到代理事件,为方便管理,避免代码混乱,需要一个总的事件管理器: using UnityEngine; using System.Collections; using System.Collections.Generic; using System; public class EventManager<T> { private static Dictionary<EventType,List<Action<T>>> eventDic =

phalcon:model 事件与事件管理器

事件与事件管理器(Events and Events Manager)¶ Models allow you to implement events that will be thrown when performing an insert/update/delete. They help define business rules for a certain model. The following are the events supported by Phalcon\Mvc\Model an

storm事件管理器EventManager源码分析-event.clj

storm事件管理器定义在event.clj中,主要功能就是通过独立线程执行"事件处理函数".我们可以将"事件处理函数"添加到EventManager的阻塞队列中,EventManager的事件处理线程不断地从阻塞队列中获取"事件处理函数"并执行. EventManager协议 协议就是一组函数定义的集合,协议中函数的第一个参数必须为实现该协议的实例本身,类似于java中实例方法的第一个参数为this:协议类似于java中的接口. (defpro

cocos2d-js v3事件管理器

总概: 1.时间监听器(cc.EventListener)封装用户的事件处理逻辑. 2.事件管理器(cc.eventManager)管理用户注册的事件监听器. 3.事件对象(cc.Event)包含事件相关信息的对象. 事件监听器包含以下几种类型: 1.触摸事件监听器(cc.EventListenerTouch) 2.键盘事件监听器(cc.EventListenerKeyboard) 3.加速计事件监听器(cc.EventListenerAcceleration) 4.鼠标事件监听器(cc.Eve

【Python学习笔记】with语句与上下文管理器

with语句 上下文管理器 contextlib模块 参考引用 with语句 with语句时在Python2.6中出现的新语句.在Python2.6以前,要正确的处理涉及到异常的资源管理时,需要使用try/finally代码结构.如要实现文件在操作出现异常时也能正确关闭,则需要像如下实现: f = open("test.txt") try: for line in f.readlines(): print(line) finally: f.close() 不管文件操作有没有出现异常,t

安卓开发:UI组件-布局管理器和文本显示

接下来的随笔,记录了在学习b站up主:天哥在奔跑,录制的教学视频的同时,进行一个app开发. up主:天哥在奔跑 视频地址:https://www.bilibili.com/video/av38409964?from=search&seid=1641333322970886700 开发app:师傅网 2.1布局管理器 每个界面上元素有很多,各元素相互之间的摆放位置与元素关系,就由布局管理器完成.常用的两种布局为线性布局(LinearLayout)和相对布局(RelativeLayout). 2.

UI复习-布局管理器FrameLayout(霓虹灯)

1>帧概念,在该布局内的组件,类似window编程的card层叠在一起 package com.brady.est; import java.util.Timer; import java.util.TimerTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.ActionBarActivity; import and

UI复习-布局管理器GridLayout(计算器界面)

1>GridLayout,4.0版本以上新增的网格布局,以下版本需要引用支撑包 package com.brady.est; import android.annotation.SuppressLint; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.Gravity; import android.view.Menu; import android.vi