QTreeWidget 树遍历
创始人
2025-01-15 03:34:36
0

在项目中遇到一个问题:需要将QString路径,做成一棵树的样式展示出来。其实倒不是说是问题,只是记录写这块儿的代码的思路
前提:我的所有的QString都是用"/"进行分割的,分割后的list中第一个元素是公共的路径,也就是树的根节点
举例:

string str1 = "A/B/B1/B2"; string str2 = "A/B/B1/B3";	 string str4 = "A/C/B3"; string str5 = "A/C/B1"; string str6 = "A/B/B2"; 

具体的代码如下:

// 定义的树控件 m_treeWidget 为成员变量 m_treeWidget->clear();  // 设置根节点 QTreeWidgetItem *root = new QTreeWidgetItem(m_treeWidget); //树的根 m_treeWidget->addTopLevelItem(root); // 将所有的路径写在一个 vector 中,用于遍历 string str1 = "A/B/B1/B2"; string str2 = "A/B/B1/B3";	 string str4 = "A/C/B3"; string str5 = "A/C/B1"; string str6 = "A/B/B2"; vector vec; vec.push_back(str1); vec.push_back(str2); vec.push_back(str4); vec.push_back(str5); vec.push_back(str6); // 遍历所有路径 把所有路径按照"/"分割,保存在list中 for (int i = 0; i < vec.size(); i++) { 	QString strFirst = QString::fromStdString(vec[i]); 	// 调用 split 分割 	QStringList nameListFirst = strFirst.split('/', Qt::SkipEmptyParts);  	if (i == 0) 	{ 		// 因为所有路径的第一个名称为根节点,所以只设置一次根节点的名称 		root->setText(0, nameListFirst[0]); 	} 	// 在后续递归的时候就不用第一个根节点了 	nameListFirst.removeAt(0); 	if (!nameListFirst.isEmpty()) 	{ 		this->traverseTree(root, nameListFirst); 	} } // 设置隐藏树的头部 m_treeWidget->setHeaderHidden(true); 

递归的思想

  1. 判断当前节点的子节点个数是否为空,若为空说明有两种情况:
    当前是第一个list进入递归,树中还没有节点。或者当前节点是树的叶子节点了
    无论是哪种情况,都只需要把list中的值设置为当前节点的子节点就可以
    终止条件:list为空。list为空就说明,当前list中没有内容了,已经到叶子节点了
  2. 当前节点的子节点个数不为空,此时说明:
    当前节点已经在树中存在,那么就拿到当前节点的所有子节点,判断list[0]是否已经被包含在所有的子节点中
    如果是,说明list[0]中的名称已经存在子节点中了,则说明当前list[0]所在的节点已经在树上了,那么把list移除第一个元素,并且找到重合的节点。将移除后的list和该重合的节点作为参数传入递归中
    如果否,说明list[0]名称的节点没有在树上,这是就为树添加子节点,子节点的名称就是list[0]
    终止条件:当list为空,说明当前已经到叶子节点了,此时结束。

递归的代码

void traverseTree(QTreeWidgetItem * parent, QStringList& list) { 	if (!parent) 	{ 		return; 	} 	QString name1 = parent->text(0); 	// 获取当前节点的子节点个数 	int childCount = parent->childCount(); 	// 第一种情况,当前父节点的子节点为空,就为父节点添加子节点 	if (childCount == 0) 	{ 		QTreeWidgetItem *childItem = new QTreeWidgetItem(parent); 		// 为子节点设置名称,名称就是list[0] 		childItem->setText(0, list[0]); 		list.removeAt(0); 		// 终止条件:list为空,说明已经到了叶子节点了 		if (list.isEmpty()) 		{ 			return; 		} 		traverseTree(childItem, list); 	} 	else 	{ 		// 第二种情况,当前父节点的子节点不为空 		// 找出当前父节点的所有子节点名称,保存在list中 		QStringList nodeList; 		for (int j = 0; j < childCount; j++) 		{ 			QTreeWidgetItem *childItem = parent->child(j); 			nodeList.append(childItem->text(0)); 		} 		 		QString tempName = list[0]; 		// 如果list[0]的名称已经包含在子节点名称中,则在所有的子节点中找到同名的节点 		if (nodeList.contains(tempName)) 		{ 			QTreeWidgetItem* node = new QTreeWidgetItem(); 			for (int i = 0; i < childCount; i++) 			{ 				QTreeWidgetItem *childItem = parent->child(i); 				if (childItem->text(0) == tempName) 				{ 					node = childItem; 				}				 			} 			// 将list[0]移除 			list.removeAt(0); 			if (list.isEmpty()) 			{ 				return; 			} 			traverseTree(node, list); 		} 		// list[0]的名称不包含在子节点名称中,直接在父节点后添加子节点,节点名称就是list[0] 		else 		{		 			// 当前层不包括当前名,直接该名称追加在父节点后 			QTreeWidgetItem *childItem = new QTreeWidgetItem(parent); 			childItem->setText(0, list[0]);		 			list.removeAt(0);  			if (list.isEmpty()) 			{ 				return; 			} 			// 进入下一层迭代 			traverseTree(childItem, list);		 		} 	} } 

不得不感叹,之前写算法的时候写到树的深度和广度遍历,用纯C++写,虽然代码量也不多,但是要递归。现在用了QT,广度遍历直接一个接口就搞定了,封装好的接口真好用啊!!!

相关内容

热门资讯

绝活儿辅助!广西老友玩老是输怎... 绝活儿辅助!广西老友玩老是输怎么办(辅助挂)都是真的有辅助app(讲解有挂)在进入广西老友玩老是输怎...
法门辅助!福建13水插件(辅助... 法门辅助!福建13水插件(辅助挂)一贯是有辅助技巧(有挂技术)1、许多玩家不知道福建13水插件辅助怎...
办法辅助!潮友会app下载官方... 办法辅助!潮友会app下载官方辅助器(辅助挂)真是真的是有辅助app(有挂教程)该软件可以轻松地帮助...
妙招辅助!邯郸胡乐挂辅助(辅助... 妙招辅助!邯郸胡乐挂辅助(辅助挂)好像存在有辅助插件(有挂方略)1、上手简单,内置详细流程视频教学,...
教程书辅助!乐酷辅助(辅助挂)... 教程书辅助!乐酷辅助(辅助挂)其实存在有辅助脚本(有挂细节)乐酷辅助能透视中分为三种模型:乐酷辅助模...
学习辅助!决战卡五星辅助(辅助... 学习辅助!决战卡五星辅助(辅助挂)本来真的是有辅助软件(有人有挂)学习辅助!决战卡五星辅助(辅助挂)...
绝活辅助!边锋嘉兴麻将辅助器(... 绝活辅助!边锋嘉兴麻将辅助器(辅助挂)真是真的有辅助神器(新版有挂)1、边锋嘉兴麻将辅助器公共底牌简...
举措辅助!枫叶辅助器(辅助挂)... 举措辅助!枫叶辅助器(辅助挂)本来存在有辅助技巧(竟然有挂)1、下载好枫叶辅助器正确养号方法之后点击...
讲义辅助!点我达辅助(辅助挂)... 讲义辅助!点我达辅助(辅助挂)一直存在有辅助技巧(有人有挂)1、点我达辅助辅助器安装包、点我达辅助辅...
模块辅助!威信茶馆有挂的吗(辅... 模块辅助!威信茶馆有挂的吗(辅助挂)一直真的是有辅助脚本(揭秘有挂)1、玩家可以在威信茶馆有挂的吗线...