Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

移除TreeView时报错 #85

Closed
smallevilbeast opened this issue Jul 23, 2019 · 8 comments
Closed

移除TreeView时报错 #85

smallevilbeast opened this issue Jul 23, 2019 · 8 comments
Assignees
Labels
bug Something isn't working

Comments

@smallevilbeast
Copy link
Contributor

smallevilbeast commented Jul 23, 2019

treeview的父级box移除treeview时, 会报错
Unhandled exception at 0x75142CD2 in controls_d.exe: Microsoft C++ exception: std::__non_rtti_object at memory location 0x0096CF04.

pBox->Remove(pTreeView);

运行时会直接闪断

image

@nmgwddj nmgwddj added the bug Something isn't working label Jul 23, 2019
@smallevilbeast
Copy link
Contributor Author

https://github.com/netease-im/NIM_Duilib_Framework/blob/master/tool_kits/duilib/Core/Window.cpp#L974
Window这里执行了delete

		for (auto it = m_aDelayedCleanup.begin(); it != m_aDelayedCleanup.end(); it++)	delete *it;
		m_aDelayedCleanup.clear();

https://github.com/netease-im/NIM_Duilib_Framework/blob/master/tool_kits/duilib/Core/Box.cpp#L213
Delete调用了box的析构函数

Box::~Box()
{
	m_bDelayedDestroy = false;
	RemoveAll();
}

RemoveAll

void Box::RemoveAll()
{
	if (m_bAutoDestroy) {
		for (auto it = m_items.begin(); it != m_items.end(); it++) {
			if( m_bDelayedDestroy && m_pWindow ) m_pWindow->AddDelayedCleanup((*it));             
			else delete (*it);
		}
	}

	m_items.clear();
	Arrange();   //  析构时,给RemoveAll传一个参数不让arrange 可以解决这个问题
}

Arrange(); 析构时,给RemoveAll传一个参数不让arrange 可以解决这个问题, 奇怪的只有Remove TreeView的时候会出错

@nmgwddj
Copy link
Collaborator

nmgwddj commented Jul 24, 2019

问题原因

在控件插入时,将所有的子控件都插入为 TreeView 的子节点,由于 TreeNode 重写了 SetWindow 方法,在 SetWindow 时,将要添加的子节点父容器设置为 ParentNode 了。
而销毁时是根据 TreeView 的所有子节点(一维的数据,非树形结构)数组依次进行销毁的,类似 ListBox 的做法,但由于并非所有子节点的父容器都是 TreeView 或 TreeView 中隐藏的 RootNode,导致第一个 ParentNode 被销毁时,后面的子节点就获取不到父容器指针了。

解决方案

将所有 TreeNode 的父容器都设置为 TreeView 中隐藏的 RootNode,而不影响 GetParentNode 方法,在整个 TreeView 销毁时,RootNode 由于是一个智能指针,也会跟随销毁。

@nmgwddj nmgwddj closed this as completed Jul 24, 2019
@smallevilbeast
Copy link
Contributor Author

辛苦啦 3Q

@smallevilbeast
Copy link
Contributor Author

@nmgwddj 测试了下, 问题依然存在

在controls项目 可以测试下

	ui::Button* btn = dynamic_cast<ui::Button*>(FindControl(L"btn_blue"));
	btn->AttachClick([tree](ui::EventArgs* args)->bool{
		tree->GetParent()->Remove(tree);
		return false;
	});

@nmgwddj
Copy link
Collaborator

nmgwddj commented Jul 25, 2019

@lovesnow 好的,感谢反馈,我试了一下的确还存在,可能我修改的时候本地有缓存代码没有上传,现在被 reset 掉了。

@nmgwddj nmgwddj reopened this Jul 25, 2019
nmgwddj added a commit that referenced this issue Jul 25, 2019
This reverts commit f811e98.

Signed-off-by: jiajia_deng <[email protected]>
@nmgwddj
Copy link
Collaborator

nmgwddj commented Jul 25, 2019

@lovesnow c627eff
我 revert 了之前的提交,重新梳理了一下移除的流程,你可以拉取一下最新代码来测试一下。具体的原因我稍后会补上。

@smallevilbeast
Copy link
Contributor Author

@nmgwddj 测试了下 controls的例子 正常, 但是我项目上使用这个还是会出错, 我再看看 是什么原因 晚点再反馈

@nmgwddj
Copy link
Collaborator

nmgwddj commented Jul 25, 2019

@lovesnow 可以提供下最小化示例我们一起排查一下。

QWarGod pushed a commit to QWarGod/NIM_Duilib_Framework that referenced this issue Jun 18, 2021
 - Set all of the child node parent is root node.

Signed-off-by: jiajia_deng <[email protected]>
QWarGod pushed a commit to QWarGod/NIM_Duilib_Framework that referenced this issue Jun 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants