网上关于NXOpen::BlockStyler::Tree的例子不是太多,控件默认id名称为tree_control01,因为例子不多很多功能得自己写,虽然NXOpen::BlockStyler::Tree的封装已经不错了,但是实际使用起来也不是很方便,比如像获取所有节点,指定节点的子节点等功能,都没有直接实现,而如果想实现层级关系,则更是没得,需要自己整理而且经过繁琐验证,这些工作我已经做过了,并且经过了时间的考验,于是特此分享出来,注意每个函数的功能我都已经写好注释了。
首先是声明:
//author:autumoon
//联系:9506@163.com
//日期:2023-07-05
class CNXTreeCtrlUser
{
public:
CNXTreeCtrlUser();
~CNXTreeCtrlUser(void);
public:
//在某个节点下最后添加一个节点并且自动展开
bool AddExpandNode(BlockStyler::Node* pNewNode, BlockStyler::Node* pParentNode);
//在某个节点的同级别最后处添加一个节点并且自动展开
bool AddTheSameLevelExpandNode(BlockStyler::Node* pNewNode, BlockStyler::Node* pTheSameLevelNode);
//树是否可用
void EnableTreeCtrl(bool bEnabled = true);
//设置树列表高度
void SetTreeHeight(int nHeight = 300);
//设置控件指针
void SetTreePtr(BlockStyler::Tree * tree){m_pTreeCtrl = tree;}
public:
//判断某个节点是不是对应的级别
static bool IsLevelNode(BlockStyler::Tree* tree, BlockStyler::Node* inputNode, int nLevel);
//清空某个节点的子节点
static void ClearChildNodes(BlockStyler::Tree* tree, BlockStyler::Node* inputNode);
//清空某个级别以及以上的子节点 nLevel = 0时清空所有 等于1时保留根节点 等于2时保留根节点以及第二级 以此类推
static void ClearTreeLevelNodes(BlockStyler::Tree* tree, int nLevel = 1);
//获取某个级别的节点 nLevel = 0时所有 等于1时获得第一级 以此类推 bIncludeChild控制是否包该级别的子节点
static void GetTreeLevelNodes(BlockStyler::Tree* tree, std::vector<BlockStyler::Node*> &nodes, int nLevel = 1, bool bIncludeChild = false);
//遍历某个节点的子节点,之所以写成这种形式,是为了方便添加多个节点 bIncludeChild控制是否包含子节点
static void GetChildNodes(BlockStyler::Node* inputNode, std::vector<BlockStyler::Node*> &nodes, bool bIncludeChild = true);
//得到树控件所有节点 bIncludeChild控制是否包含子节点
static std::vector<BlockStyler::Node*> GetAllNodes(BlockStyler::Tree* tree, bool bIncludeChild = true);
//清空树节点
static void ClearTree(BlockStyler::Tree* tree);
protected:
BlockStyler::Tree * m_pTreeCtrl;
};
接着是实现:
//author:autumoon
//联系:9506@163.com
//日期:2023-07-05
using namespace NXOpen::BlockStyler;
CNXTreeCtrlUser::CNXTreeCtrlUser(void):m_pTreeCtrl(nullptr)
{
}
CNXTreeCtrlUser::~CNXTreeCtrlUser(void)
{
}
bool CNXTreeCtrlUser::AddExpandNode(BlockStyler::Node* pNewNode, BlockStyler::Node* pParentNode)
{
if (pNewNode == nullptr || pParentNode == nullptr)
{
return false;
}
m_pTreeCtrl->InsertNode(pNewNode, pParentNode, nullptr, Tree::NodeInsertOptionLast);//子节点
pNewNode->Expand(Node::ExpandOptionExpand);
return true;
}
bool CNXTreeCtrlUser::AddTheSameLevelExpandNode(BlockStyler::Node* pNewNode, BlockStyler::Node* pTheSameLevelNode)
{
if (pNewNode == nullptr || pTheSameLevelNode == nullptr)
{
return false;
}
m_pTreeCtrl->InsertNode(pNewNode, pTheSameLevelNode->ParentNode(), nullptr, Tree::NodeInsertOptionLast);//子节点
pNewNode->Expand(Node::ExpandOptionExpand);
return true;
}
void CNXTreeCtrlUser::EnableTreeCtrl(bool bEnabled /*= true*/)
{
if (m_pTreeCtrl)
{
m_pTreeCtrl->GetProperties()->SetLogical("Enable", bEnabled);
}
}
void CNXTreeCtrlUser::SetTreeHeight(int nHeight /*= 300*/)
{
if (m_pTreeCtrl)
{
this->m_pTreeCtrl->GetProperties()->SetInteger("Height",300);//设置树列表高度
}
}
bool CNXTreeCtrlUser::IsLevelNode(BlockStyler::Tree* tree, BlockStyler::Node* inputNode, int nLevel)
{
std::vector<Node*> vNodes;
GetTreeLevelNodes(tree, vNodes, nLevel, false);
size_t nNodeCount = vNodes.size();
for (size_t i = 0; i < nNodeCount; ++i)
{
if (vNodes[i] == inputNode)
{
return true;
}
}
return false;
}
void CNXTreeCtrlUser::ClearChildNodes(BlockStyler::Tree* tree, BlockStyler::Node* inputNode)
{
if (tree && inputNode)
{
std::vector<BlockStyler::Node*> nodes;
GetChildNodes(inputNode, nodes, false);
for (size_t i = 0; i < nodes.size(); i++)
{
tree->DeleteNode(nodes[i]);
}
}
}
void CNXTreeCtrlUser::ClearTreeLevelNodes(BlockStyler::Tree* tree, int nLevel /*= 1*/)
{
if (tree && nLevel >= 0)
{
Node* pRootNode = tree->RootNode();
//每个层级的node由对应的层级的vector存储
std::vector<Node*> vNodes;
GetTreeLevelNodes(tree, vNodes, nLevel);
for (size_t i = 0; i < vNodes.size(); i++)
{
tree->DeleteNode(vNodes[i]);
}
}
}
void CNXTreeCtrlUser::GetTreeLevelNodes(BlockStyler::Tree* tree, std::vector<BlockStyler::Node*> &nodes, int nLevel /*= 1*/, bool bIncludeChild /*= false*/)
{
if (tree && nLevel >= 0)
{
Node* pRootNode = tree->RootNode();
//每个层级的node由对应的层级的vector存储
std::vector<std::vector<Node*>> vvNodes(nLevel + 1);
//可能有多个根节点
while (pRootNode)
{
vvNodes[0].push_back(pRootNode);
pRootNode = pRootNode->NextSiblingNode();
}
//满足条件则继续,但不允许循环超过1000次,避免死循环
int nLoopCount = 0, nMaxLoop = 1000;
int nCurLevel = nLevel;
while(nCurLevel-- > 0)
{
if (++nLoopCount > nMaxLoop)
{
break;
}
int nLastLevelIndex = nLevel - nCurLevel - 1;
std::vector<Node*>& vCurLevelRoots = vvNodes[nLastLevelIndex];
int nCurLevelIndex = nLastLevelIndex + 1;
for (size_t i = 0; i < vCurLevelRoots.size(); ++i)
{
GetChildNodes(vCurLevelRoots[i], vvNodes[nCurLevelIndex], false);
}
}
nodes.insert(nodes.end(), vvNodes[nLevel].begin(), vvNodes[nLevel].end());
}
}
void CNXTreeCtrlUser::GetChildNodes(BlockStyler::Node* inputNode, std::vector<BlockStyler::Node*> &nodes, bool bIncludeChild /*= true*/)
{
if (inputNode)
{
Node* node = inputNode->FirstChildNode();
while (node != nullptr)
{
nodes.push_back(node);
if (bIncludeChild)
{
GetChildNodes(node, nodes);
}
node = node->NextSiblingNode();
}
}
}
std::vector<NXOpen::BlockStyler::Node*> CNXTreeCtrlUser::GetAllNodes(BlockStyler::Tree* tree, bool bIncludeChild /*= true*/)
{
Node *nd = tree->RootNode();
std::vector<Node*> res;
while (nd != nullptr)
{
res.push_back(nd);
if (bIncludeChild)
{
GetChildNodes(nd, res);
}
nd = nd->NextSiblingNode();
}
return res;
}
void CNXTreeCtrlUser::ClearTree(Tree* tree)
{
if (tree)
{
std::vector<BlockStyler::Node*> vNodes = GetAllNodes(tree, false);
for (size_t i = 0; i < vNodes.size(); i++)
{
tree->DeleteNode(vNodes[i]);
}
}
}
如果在使用中遇到什么问题,欢迎交流与讨论。