当前位置:   article > 正文

QTreeWidget 树遍历

QTreeWidget 树遍历

在项目中遇到一个问题:需要将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";
  • 1
  • 2
  • 3
  • 4
  • 5

具体的代码如下:

// 定义的树控件 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<string> 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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

递归的思想

  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);		
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/810692
推荐阅读
相关标签
  

闽ICP备14008679号