cocos2d-x 2.2.2 中cocostudio控件TouchGroup触摸事件

cocostudio编辑器中的控件都是继承自Widget,这些控件都被添加到TouchGroup层中。所有的控件事件的接
收都是依靠最外层的TouchGroup传递的。

TouchGroupj继承自CCLayer,重写了CCTouchDelegate的四个方法。

bool TouchGroup::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
    return checkEventWidget(pTouch, pEvent);
}

bool TouchGroup::checkEventWidget(CCTouch* touch, CCEvent *pEvent)
{
    checkTouchEvent(m_pRootWidget,touch, pEvent);
    return (m_pSelectedWidgets->count() > 0);
}
    
bool TouchGroup::checkTouchEvent(Widget *root, CCTouch* touch, CCEvent* pEvent)
{
    /*这个数组,每一帧在visit方法中根据ZOder排好序的(详见Widget的sortAllChildren方法),
       所以在TouchGroup中ZOder越大,先接收到事件*/
    ccArray* arrayRootChildren = root->getChildren()->data;
    int length = arrayRootChildren->num;
    for (int i=length-1; i >= 0; i--)
    {
        Widget* widget = (Widget*)(arrayRootChildren->arr[i]);
        if (checkTouchEvent(widget, touch, pEvent))
        {
            return true;
        }
    }
    bool pass = root->onTouchBegan(touch, pEvent);
    if (root->_hitted)
    {
        m_pSelectedWidgets->addObject(root);
        return true;
    }
    return pass;
}



其中ccTouchBegan方法调用了checkEventWidget,checkEventWidget调用了checkTouchEvent。
checkTTouchEvent是一个递归函数。会递归检查TouchGroup中m_pRootWidget的子节点。
这里有一点值得要提的是往TouchGroup里加控件不要用addChild,要用addWidget,因为触摸事件检查的节点是m_pRootWidget为根的树,所有直接加到TouchGroup中是接收不到触摸事件的。
void TouchGroup::addWidget(Widget* widget)
{
    m_pRootWidget->addChild(widget);
}

当控件没有子节点会调用Widget中的onTouchBegan中的检查控件的Enable,TouchEnable和hitTest。
所以Cocostudio的控件隐藏用setEnbale(false),不要用setVisible(false).setVisible只是不渲染,但是还是
会接收到事件的,setEnbale的话在渲染和事件的接收都会做判断的。
bool Widget::onTouchBegan(CCTouch *touch, CCEvent *unused_event)
{
    _hitted = false;
    if (isEnabled() && isTouchEnabled())
    {
        _touchStartPos = touch->getLocation();
        if(hitTest(_touchStartPos) && clippingParentAreaContainPoint(_touchStartPos))
        {
            _hitted = true;
        }
    }
    if (!_hitted)
    {
        return false;
    }
    setFocused(true);
   //先传递给父节点处理
    Widget* widgetParent = getWidgetParent();
    if (widgetParent)
    {
        widgetParent->checkChildInfo(0,this,_touchStartPos);
    }
    pushDownEvent();
    return !_touchPassedEnabled;
}


这其中还有一个机制,就是当一个控件接收到事件之后,会先传递给父节点处理.
其中checkChildInfo是个虚函数.控件可以重写这个方法,来接收处理子节点穿过来的事件。
 virtual void checkChildInfo(int handleState,Widget* sender,const CCPoint &touchPoint);
其中handleState的值0为begin.1为move,2为end,3为cancel。
这个方法,一般的控件是没有重写的,也就是继续往父节点传,而不做处理。
只有ScrollView,PageView重写这个函数。
void ScrollView::checkChildInfo(int handleState,Widget* sender,const CCPoint &touchPoint)
{
    interceptTouchEvent(handleState, sender, touchPoint);
}


基本上就这些了。

还有一问题就是onTouchEnd,onTouchCanel两个个方法都是在什么时候触发。
在Widget中的ccTouchBegan方法中如果控件检查符合条件被击中则setFocused(true)
ccTouchMoved中在移动的过程中会检查移动的点是否还在控件内,来设置焦点。
setFocused(hitTest(_touchMovePos));
在onTouchEnded中会检查控件是否获得焦点,如果获得焦点正常releaseUpEvent
没有焦点cancelUpEvent

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值