【 每日·槽】第1话 -- 论setEnabled和setVisible

本节目纯属扯淡,如有得罪,还请。。。。。。有本事你来打我呀!!!

【 每日·槽】第1话 – 论setEnabled和setVisible
每日槽,何弃疗?

(Cocos2d-x3.4起 二者功能相同= =)// <-前面是版主留的话,时隔一年他们终于相(想)同(通)了

最近setEnabled和setVisible这两个货坑了不少兄弟,所以今天先把这对妖怪拉出来,研究一下。

本屌想做一个MessageBox,用来提示用户一些信息。当提示框显示的时候用户无法点击提示框后其他控件。
MsgBox.ExportJson是我在编辑器里做的界面。蓝色的按钮是代码添加的。代码如下:

    this._msgBox = ccs.GUIReader.getInstance().widgetFromJsonFile('MsgBox.ExportJson');
    this.addChild(this._msgBox);

    var button2 = ccui.Button.create();
    button2.setTouchEnabled(true);
    button2.loadTextures("res/animationbuttonnormal.png", "res/animationbuttonpressed.png", "");
    button2.setPosition(cc.p(200, 200));

    this.addChild(button2);

如下图:现在所有按钮都可以点击,我想让弹出确认框的时候,后面蓝色的按钮无法响应。

让其他界面不响应事件嘛,简单,我首先想到了:setEnabled(false)。字面上看就是让widget不能用嘛。但。。。使用后的效果。。。。

小按钮你肿么了,小按钮你怎么没了!小按钮我不能没有你啊!:cry: :6:
我只是想让它不能用,怎么它却不显示了?!坑爹啊!怒翻猿马:

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

原来_enabled为false之后不visit了,所以就不显示了。怒改之,去掉if判断。void Layout::visit()里也有这个问题,一并删掉!

setEnabled(false)之后控件正常显示,只是不能点击。哦了~顿时心情舒畅。:14:

后来在论坛上发现另一个兄弟发的帖子:http://www.cocoachina.com/bbs/read.php?tid=181066&page=e&#a
他遇到的问题和本屌有异曲同工之妙~简直就是鬼斧神工浑然天成。

他以为控件隐藏之后控件就不响应touch事件了,但他错了哦哈哈哈哈哈哈哈哈哈哈好。其实本屌之前也遇到过这个问题,不过本屌一眼就看穿了这个开发者的小阴谋,
所以本屌一直是setVisible(false)和setEnabled(false)一起用的,不用改源码,也不用像版主说的那样将控件移到屏幕外,绿色环保低碳高效,有木有~有木有~?。哈哈哈哈,想这样就把本屌坑了,智商拙计!!!too simple, too naive!

———————————————华丽分割线—————————————————————
啰嗦了这么多废话,总结一下:

setEnabled(false):会让widget不可使用,并且隐藏。
但是只从名字上来看,本屌嗅不到任何会隐藏的讯息,既然它能隐藏那还要setVisible干嘛?干好自己的事情就行了,还操起setVisible的心,多事! 我们想隐藏的话,自然会调用setVisible(false),不用你操这闲心,蛋疼!不如改名叫setEnableAndVisible!
坑爹指数:★★★★ 4颗星

setVisible(false):会让widget隐藏,但依然可用!
像看不到的幽灵,你看不到但它仍在那里!听起来好诡异,好怕怕! :8:
坑爹指数:★★★ 3颗星 ★★★★ 4颗星 虽然它没怎么坑过我,但考虑到它仍坑了不少兄弟,评分组委会决定为它追加一颗星^_^

本期的 每日·槽 就到这里啦,如果对你有帮助的话就顶一下吧~


往期回顾:

【 每日·槽】第1话 – 论setEnabled和setVisible
http://www.cocoachina.com/bbs/read.php?tid=181496

【 每日·槽】第2话 – 模态窗口的制作
http://www.cocoachina.com/bbs/read.php?tid=181959

【 每日·槽】第3话-- UITextField的七宗罪 http://www.cocoachina.com/bbs/read.php?tid=182207

【 每日·槽】第4话-- UI
TextField 中文字符的长度检测问题

http://www.cocoachina.com/bbs/read.php?tid=182207

每日·槽】第5话 – 2014CocoaChina春季开发者大会实吐
http://www.cocoachina.com/bbs/read.php?tid=194385

:2:问楼主个问题,子控件的管理你怎么弄呢?

你说的管理是指?
我现在是用 ccui.Helper.seekWidgetByName 获取到需要的控件,存起来,然后想怎么用怎么用啊:7:

楼主加油,写个系列哟!

Gary亲自回复,本屌受宠若惊啊!!!:870: :870: :870:

对于setEnable和setVisible的这种机制,我也是一时无法理解(直到现在也没有理解),不过还好,没有特别大的影响

欢迎更新~:14::14::14::14:

我说的是子控件的触摸不受父级的影响,父级隐藏了,你可以将所有的所有子集遍历取消触摸,但是状态恢复将会变得比较麻烦,需要记录每个子控件的状态才行我不喜欢改引擎的东西,因为我即使改了也只是暂时的~所以之前将控件移出屏幕外倒是一个更简单的方法。

不知我理解的对不对,你是这个意思吗,我举个栗子:chestnut:
父节点:A,它有5个子控件:1,2,3,4,5。 你说的子控件状态是指它是否可以被点击吗?那假设3不能点击。
隐藏A后,再将A设置setEnabled(false); 会遍历所有子结点,使所有子结点_enabled也为false。
显示A后,如果再调用setEnabled(true); 会遍历所有子结点,使所有子结点_enabled也为true。

这样3就错误的变成可以点击的状态。所以要记录一下吗?

差不多是这个意思,最新版本我不清楚是不是还是这样,但以前确实是这个问题~~~

其实之前我也遇到过这个问题,的确是按照你说的用一个字典记录了子控件的状态。但我后来发现用setTouchEnabled函数就可以解决这个问题。还是上面那个栗子:chestnut:

初始状态所有控件都可以点击,
_3.setTouchEnabled(false); //3变为不能点击。
A.setEnabled(false); // 所有控件隐藏,并且都不能点击。
A.setEnabled(true); // 所有控件都显示了,但这个时候3还是不能点击,因为之前用的 setTouchEnabled(false),还在起作用。

这样就不用记录子控件的状态了。

可是这样还是要自己去管理~~~
本身这事就不应该交给用户~~~~:10:

好专业的啊,强制围观

我去,楼主好人才,点个赞。

拜读完LZ的大作

不明觉厉

:13::13::13:

messageBox这种东西,可以用一个layer,layer的touch事件用空函数,messageBox放在layer上,然后messageBox弹出来的时候自然就屏蔽其他的东西了,我项目里就这么搞的,而且layer里还可以加你想加的图片,比如messageBox弹出来的时候加个半透明的灰图片让背景暗下去。。。

还有像网络请求、loading等待之类需要等待的,都可以搞个loading界面之类的,用个屏蔽层加上想显示的loading信息,屏蔽掉touch,等请求返回了才移除屏蔽,免得有些地方玩家一顿狂点。

是的,我在【 每日·槽】第2话里用的就是这种方法,这个帖子主要说setEnabled,messageBox只是个引子,就没细讲。

小意思的啦,如果头像是你本人的话我们还可以去喝啤酒,吃小龙虾,然后找个安静的地方探讨人生呀!:872:

我今天又被这个问题坑了。
前几天有两个VIEW做了隐藏,以为就没事了。过了几天忘记了这事,然后某一些东西无法点击了。查了半天。。原来是setvisible惹的祸,被盖住了,瓦擦!
悲剧啊!