摘要: 主要解决cocos2dx-2.2.2版本中, UIButton显示不了disable状态图的问题. 顺便, 理解了一下cocos2dx中UIWidget的渲染原理.



发现问题



在cocostudio中添加一个UIButton组件, 我们可以看到通常以一下按钮的三态:normal,pressed,disable. 但是,当我们设置了disable状态之后, 在我们的游戏项目中, 对某个按钮执行button->setEnable(false)后, 按钮居然完全不见了?!

解决方法

  1. 修改Widget::visit()方法, 改为:

    void Widget::visit()
    {
    CCNodeRGBA::visit();
    }

    即, 删除if判断.

  2. 修改Widget::setEnable()方法, 改为:

    void Widget::setEnabled(bool enabled)
    {
    _enabled = enabled;
    if(_widgetChildren && _widgetChildren->count() > 0)
    {
    CCObject* child;
    CCARRAY_FOREACH(_widgetChildren, child)
    {
    ((Widget*)child)->setEnabled(enabled);
    }
    }
    setBright( enabled );//增加此行
    }

    即, 增加setBright( enabled );行.

如果想知其所以然的, 下面是解释.

解释

Widget的诡异渲染

Widget::visit()的实现如下:

void Widget::visit()
{
if (_enabled)
{
CCNodeRGBA::visit();
}
}

如果您没时间仔细看过cocos2dx的源码, 这里可以有一个简单的解释:

1. visit()方法最初是从CCNode继承过来的. 也就是说任何显示对象都有这个方法.

2. CCNode::visit()就是CCNode的渲染函数, 是视图渲染中最重要的一个函数, 跟IOS开发中的UIView::draw()功能类似. 框架在每一帧都会调用这个方法, 而这个方法负责当前组件的openGL绘制. 我们可以看下CCNode::visit()的实现来作为验证:

void CCNode::visit()
{
...
this->draw();
...
}
//算了, 这段代码有点长, 有些人时间比较宝贵可能没兴趣看. 我就放在***附录***了.(*^__^*)

看到这里, 你肯定一经发现问题了: 为什么只有在_enabledtrue的时候才渲染?难道不是坑爹么?disable状态就不理了么?

可能cocos2dx另有打算, 我没理解清楚. 不过这个功能既然不符合我的要求, 我就果断的把那个if去掉了. (谁让咱们是程序员呢?).

但是, 问题并没有完全结束. 还是没有显示disable状态.

Widget的enable?

UIButton::setEnable()方法比较短, 贴出来看看.

void Widget::setEnabled(bool enabled)
{
_enabled = enabled;
if(_widgetChildren && _widgetChildren->count() > 0)
{
CCObject* child;
CCARRAY_FOREACH(_widgetChildren, child)
{
((Widget*)child)->setEnabled(enabled);
}
}
}

发现这段代码除了把_enable和所有孩子的_enable状态设为false, 没做任何事情. 通过查看widget的代码, 很容易看到, widget的三态是通过下面的是三个函数实现的:

void Widget::onPressStateChangedToNormal(){}
void Widget::onPressStateChangedToPressed(){}
void Widget::onPressStateChangedToDisabled(){}

不错,他们都是空函数.子类根据需要来实现这三个函数.

下面是setBright的实现:

void Widget::setBright(bool bright)
{
_bright = bright;
if (_bright)
{
_brightStyle = BRIGHT_NONE;
setBrightStyle(BRIGHT_NORMAL);
}
else
{
onPressStateChangedToDisabled();
}
}

由上代码可以看出. 而我们调用setBright(false), 即可根据widget当前的状态, 渲染不同的图像.

附录

代码片段一CCNode::visit()

void CCNode::visit()
{
// quick return if not visible. children won't be drawn.
if (!m_bVisible)
{
return;
}
kmGLPushMatrix(); if (m_pGrid && m_pGrid->isActive())
{
m_pGrid->beforeDraw();
} this->transform(); CCNode* pNode = NULL;
unsigned int i = 0; if(m_pChildren && m_pChildren->count() > 0)
{
sortAllChildren();
// draw children zOrder < 0
ccArray *arrayData = m_pChildren->data;
for( ; i < arrayData->num; i++ )
{
pNode = (CCNode*) arrayData->arr[i]; if ( pNode && pNode->m_nZOrder < 0 )
{
pNode->visit();
}
else
{
break;
}
}
// self draw
this->draw(); for( ; i < arrayData->num; i++ )
{
pNode = (CCNode*) arrayData->arr[i];
if (pNode)
{
pNode->visit();
}
}
}
else
{
this->draw();
} // reset for next frame
m_uOrderOfArrival = 0; if (m_pGrid && m_pGrid->isActive())
{
m_pGrid->afterDraw(this);
} kmGLPopMatrix();
}

Written with StackEdit.

[cocos2dx] 让UIButton支持disable状态的更多相关文章

  1. [cocos2dx]让CCScrollView支持分页

    [cocos2dx]让CCScrollView支持分页 做过IOS开发的朋友, 肯定知道UIScrollView有一个isPaged属性. 当设置其为true的时候, 滑动会自动分页. 即, 每次滑动 ...

  2. UICollectionViewCell选中高亮状态和UIButton的高亮状态和选中状态

    UICollectionViewCell选中高亮状态 //设置点击高亮和非高亮效果! - (BOOL)collectionView:(UICollectionView *)collectionView ...

  3. AndroidTips:selector的disable状态为什么无效?

    正确的姿势: <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android=& ...

  4. UIButton在Disabled状态下标题混乱的问题

    最近开发中遇到的问题汇总 有段时间没有归纳开发中遇到的一些问题了,今天就写一下之前开发中遇到的几个问题.希望这 篇文章能让读者在以后的开发中少走弯路.本文将依次介绍<UIButton在Disab ...

  5. 移动开发之浅析cocos2d-x的中文支持问题

    题记:这阵子一直在学习cocos2d-x,其跨平台的特性确实让人舒爽,引擎的框架概念也很成熟,虽然相应的第三方工具略显单薄,但也无愧是一件移动开发的利器啊,有兴趣的朋友有时间就多了解吧. 使用引擎的过 ...

  6. 求解: Windows Phone XAML Controls 为什么是disable状态?

    问题 : 我在做一个windows phone 的App,显示一个web 返回来的data,现在想用控件ListView 去绑定这个Data,但是 为何我的VS2012 中的 ToolBox 的XAM ...

  7. js判断元素是否是disable状态

    js判断元素是否是disable状态 jquery判断元素状态用$(select).prop(属性值) == true js判断button是否可以点击: //判断button是否为不可点击状态 if ...

  8. 我的Android进阶之旅------>Android中StateListDrawable支持的状态

    Android中StateListDrawable支持的状态 android:state_active 代表是否处于激活状态 android:state_checked  代表是否处于已勾选状态 an ...

  9. UIButton在不同状态下显示不同背景色

    参考自:原文地址(内容与原文并无区别,只是自己以后方便使用整理了一下) 1.UIButton的background是不支持在针对不同的状态显示不同的颜色. 2.UIButton的backgroundI ...

随机推荐

  1. JPA学习(2)注解

    上一篇学习了JPA的helloworld,也初略的使用了一些注解,接下来就细细的了解一下有哪些注解,和这些注解的作用 JPA的基本注解: ①@Entity,@Table,@Id,@GeneratedV ...

  2. mybatis中自建的类型别名

    在使用mybatis过程中经常用到类型别名,除了我们自己新建的别名外,mybatis还自带了很多类型别名和java中的类型的映射,下面先看一个自建的别名的配置 <typeAliases> ...

  3. SwipeRefreshLayout下拉刷新

    1.SwipeRefreshLayout是Google在support v4 19.1版本的library更新的一个下拉刷新组件,实现刷新效果更方便. 弊端:只有下拉 //设置刷新控件圈圈的颜色 sw ...

  4. Java字符串格式化String.format常用用法

    常规的格式化 String类的format()方法用于创建格式化的字符串以及连接多个字符串对象.熟悉C语言的同学应该记得C语言的sprintf()方法,两者有类似之处.format()方法有两种重载形 ...

  5. CentOS安装Erlang

    1.首先要安装编译源码用的编译器gcc&g++,安装方式很简单,先用yum search gcc搜索出包,然后选择适合自己的版本复制全名,用yum intall gcc_XXX来进行安装即可. ...

  6. VM虚拟机忘记密码

    关掉虚拟机. VM->Settings,选中Hard Disk,在右边出现了Utilities的一个下拉栏,OK,点击它选择Map,这时弹出一个"Map Virtual Disk&qu ...

  7. CSS的一些小事

    1.什么时候能将零散的图片整合成一张大图,达到减少请求数的作用? 答:整合进大图的图片是被设置no-repeat用的,如果是repeat-x.repeat-y就不可以. 2.E + F 选择紧贴在E元 ...

  8. SVG描边动画原理

    SVG描边动画原理其实很简单,主要利用以下两个属性 stroke-dasharray 制作虚线,使得黑白相间, stroke-dashoffset 使得虚线向开头偏移,这里的1500不精确,是我随便取 ...

  9. HTML 5 中的标准属性

    HTML 全局属性 HTML 属性赋予元素意义和语境. 下面的全局属性可用于任何 HTML 元素. (5)= HTML5 中添加的属性. 属性 描述 accesskey 规定激活元素的快捷键. cla ...

  10. 安卓开发-See the log file\.metadata\.log.

    今天在给安卓项目res-valus-string.xml 中字符串修改的时候,突然eclipse卡住了 然后任务管理器关掉之后,重新打开 显示一个错误 百度了一下 eclipse启动报错,让查看.me ...