关于cocos2dx widget窗口中的关闭按钮 删除自身 的时候崩溃bug
2015-04-07 20:35
267 查看
回调函数里判断是弹起事件时会调用UIButton的removeFromParent方法,这时会导致游戏崩溃,代码中断在void
Widget::onTouchEnded(Touch *touch, Event *unusedEvent)方法里的releaseUpEvent()调用处。
响应UIButton的触摸弹起事件时,删除UIButton控件崩溃
view plaincopy
解决办法
void Widget::releaseUpEvent()
{
if (_touchEventListener && _touchEventSelector)
{
(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_ENDED);
}
if (_touchEventCallback) {
_touchEventCallback(this, TouchEventType::ENDED);
}
}
换个位置就好了
调用callback完以后释放本对象,但代码没执行完 继续调用Listener,这时释放的地址很可能不为空,就导致出错了。
改用
widget->runAction(RemoveSelf::create());
代替原来的removeFromParent()
原理:我们可以看看引擎对removeSelf的实现
[cpp]
view plaincopy
//
// Remove Self
//
RemoveSelf * RemoveSelf::create(bool isNeedCleanUp /*= true*/)
{
RemoveSelf *ret = new RemoveSelf();
if (ret && ret->init(isNeedCleanUp)) {
ret->autorelease();
}
return ret;
}
bool RemoveSelf::init(bool isNeedCleanUp) {
_isNeedCleanUp = isNeedCleanUp;
return true;
}
void RemoveSelf::update(float time) {
CC_UNUSED_PARAM(time);
_target->removeFromParentAndCleanup(_isNeedCleanUp);
}
RemoveSelf *RemoveSelf::reverse() const
{
return RemoveSelf::create(_isNeedCleanUp);
}
RemoveSelf * RemoveSelf::clone() const
{
// no copy constructor
auto a = new RemoveSelf();
a->init(_isNeedCleanUp);
a->autorelease();
return a;
}
弹起事件中不是直接调用remove,而是设置一个标志,在update中检测到标志再remove.
3.修改源码
void Widget::pushDownEvent()
{
+ this->retain();
if (_touchEventCallback) {
_touchEventCallback(this, TouchEventType::BEGAN);
}
void Widget::pushDownEvent()
{
(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_BEGAN);
}
+ this->release();
}
void Widget::moveEvent()
{
+ this->retain();
if (_touchEventCallback) {
_touchEventCallback(this, TouchEventType::MOVED);
}
void Widget::moveEvent()
{
(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_MOVED);
}
+ this->release();
}
void Widget::releaseUpEvent()
{
-
+ this->retain();
if (_touchEventCallback) {
_touchEventCallback(this, TouchEventType::ENDED);
}
void Widget::releaseUpEvent()
{
(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_ENDED);
}
+ this->release();
}
void Widget::cancelUpEvent()
{
+ this->retain();
if (_touchEventCallback)
{
_touchEventCallback(this, TouchEventType::CANCELED);
void Widget::cancelUpEvent()
{
(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_CANCELED);
}
-
+ this->release();
}
Widget::onTouchEnded(Touch *touch, Event *unusedEvent)方法里的releaseUpEvent()调用处。
响应UIButton的触摸弹起事件时,删除UIButton控件崩溃
修改代码解决方法1
[plain]view plaincopy
解决办法
void Widget::releaseUpEvent()
{
if (_touchEventListener && _touchEventSelector)
{
(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_ENDED);
}
if (_touchEventCallback) {
_touchEventCallback(this, TouchEventType::ENDED);
}
}
换个位置就好了
调用callback完以后释放本对象,但代码没执行完 继续调用Listener,这时释放的地址很可能不为空,就导致出错了。
2.不需要修改引擎代码
释放的时候改用改用
widget->runAction(RemoveSelf::create());
代替原来的removeFromParent()
原理:我们可以看看引擎对removeSelf的实现
[cpp]
view plaincopy
//
// Remove Self
//
RemoveSelf * RemoveSelf::create(bool isNeedCleanUp /*= true*/)
{
RemoveSelf *ret = new RemoveSelf();
if (ret && ret->init(isNeedCleanUp)) {
ret->autorelease();
}
return ret;
}
bool RemoveSelf::init(bool isNeedCleanUp) {
_isNeedCleanUp = isNeedCleanUp;
return true;
}
void RemoveSelf::update(float time) {
CC_UNUSED_PARAM(time);
_target->removeFromParentAndCleanup(_isNeedCleanUp);
}
RemoveSelf *RemoveSelf::reverse() const
{
return RemoveSelf::create(_isNeedCleanUp);
}
RemoveSelf * RemoveSelf::clone() const
{
// no copy constructor
auto a = new RemoveSelf();
a->init(_isNeedCleanUp);
a->autorelease();
return a;
}
弹起事件中不是直接调用remove,而是设置一个标志,在update中检测到标志再remove.
3.修改源码
void Widget::pushDownEvent(){
+ this->retain();
if (_touchEventCallback) {
_touchEventCallback(this, TouchEventType::BEGAN);
}
void Widget::pushDownEvent()
{
(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_BEGAN);
}
+ this->release();
}
void Widget::moveEvent()
{
+ this->retain();
if (_touchEventCallback) {
_touchEventCallback(this, TouchEventType::MOVED);
}
void Widget::moveEvent()
{
(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_MOVED);
}
+ this->release();
}
void Widget::releaseUpEvent()
{
-
+ this->retain();
if (_touchEventCallback) {
_touchEventCallback(this, TouchEventType::ENDED);
}
void Widget::releaseUpEvent()
{
(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_ENDED);
}
+ this->release();
}
void Widget::cancelUpEvent()
{
+ this->retain();
if (_touchEventCallback)
{
_touchEventCallback(this, TouchEventType::CANCELED);
void Widget::cancelUpEvent()
{
(_touchEventListener->*_touchEventSelector)(this,TOUCH_EVENT_CANCELED);
}
-
+ this->release();
}
相关文章推荐
- 关于cocos2dx widget窗口中的关闭按钮 删除自身 的时候崩溃bug
- 关于wxwidgets图形界面的关闭窗口的按钮无效的解决办法
- (3-19)关于关闭窗口按钮的代码实现
- 关于 java swing 使用按钮关闭窗口
- 怎样点关闭按钮的时候不关掉父窗口
- 点击按钮关闭真窗口崩溃原因探讨
- C#调用迅雷的时候 自动模拟点击”下载按钮” 关闭弹出窗口
- 窗口关闭按钮的时候触发js事件
- 关于winForm窗体禁用关闭按钮的使用方法及禁用最大化、最小化窗口
- WinForm 点击按钮打开新窗口的时候关闭原来的窗口
- 关于 java swing 使用按钮关闭窗口
- Qt编程技巧 设置Widget窗口的按钮(最大化,最小化,关闭)
- 如何屏蔽掉窗口右上角的关闭按钮?
- Javascript判断是否点击了页面窗口的关闭按钮
- 为gridview删除按钮添加确认窗口
- showModalDialog/showModelessDialog实例,父窗口向子窗口传递值,子窗口设置父窗口的值,子窗口关闭的时候返回值到父窗口.关闭刷新父窗口
- 新打开的子窗口 关闭的时候 刷新父窗口
- 关于您提到使用WebServices时候遇到“基础连接以关闭”的问题
- 关于IE6和IE7关闭窗口时提示和不提示以及上传图片前的本地预览解决办法
- 关于java窗口关闭的疑问