效果

image.pngimage.png

测试json

  1. {
  2. "data": [{
  3. "id": "1",
  4. "parentId": "0",
  5. "text": "编程技术",
  6. "leaf": false,
  7. "children": [{
  8. "id": "python",
  9. "parentId": "null",
  10. "text": "python cookbook0",
  11. "leaf": false,
  12. "children": [{
  13. "id": "1-1-1",
  14. "parentId": "1-1",
  15. "text": "python cookbook1",
  16. "leaf": false,
  17. "children": [{
  18. "id": "1-1-1-1",
  19. "parentId": "1-1-1",
  20. "text": "python cookbook11",
  21. "leaf": true,
  22. "children": []
  23. }]
  24. }, {
  25. "id": "1-1-2",
  26. "parentId": "python cookbook2",
  27. "text": "123",
  28. "leaf": true,
  29. "children": []
  30. }]
  31. }, {
  32. "id": "1-2",
  33. "parentId": "null",
  34. "text": "C++",
  35. "leaf": false,
  36. "children": [{
  37. "id": "1-2-1",
  38. "parentId": "1-2",
  39. "text": "c++ prime",
  40. "leaf": true,
  41. "children": []
  42. }]
  43. }]
  44. }]
  45. }

头文件

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. class QTreeWidget;
  5. class QLineEdit;
  6. class QVBoxLayout;
  7. class QTreeWidgetItem;
  8. class Widget : public QWidget {
  9. Q_OBJECT
  10. public:
  11. Widget(QWidget* parent = nullptr);
  12. ~Widget();
  13. private:
  14. void initWidget();
  15. void initConnection();
  16. // 解析json并将指定字段添加到树节点
  17. void parseJsonRoot();
  18. void parseObject(const QJsonObject& obj, QTreeWidgetItem* itemNode);
  19. void parseArray(const QJsonArray& arr, QTreeWidgetItem* itemNode);
  20. // 树节点查找功能
  21. void findItem(const QString& text);
  22. void parentExpand(QTreeWidgetItem* item);
  23. private:
  24. QLineEdit* lineEdit;
  25. QTreeWidget* treeWidget;
  26. QVBoxLayout* vLayout;
  27. };
  28. #endif // WIDGET_H

实现

  1. #include "widget.h"
  2. #include <QByteArray>
  3. #include <QFile>
  4. #include <QJsonArray>
  5. #include <QJsonDocument>
  6. #include <QJsonObject>
  7. #include <QLineEdit>
  8. #include <QTimer>
  9. #include <QTreeWidget>
  10. #include <QTreeWidgetItem>
  11. #include <QVBoxLayout>
  12. Widget::Widget(QWidget* parent)
  13. : QWidget(parent)
  14. {
  15. initWidget();
  16. initConnection();
  17. parseJsonRoot();
  18. }
  19. Widget::~Widget()
  20. {
  21. }
  22. void Widget::initWidget()
  23. {
  24. this->setWindowTitle(tr("Json数据字段值转树节点及搜索"));
  25. this->setMinimumSize(QSize(300, 400));
  26. vLayout = new QVBoxLayout(this);
  27. lineEdit = new QLineEdit();
  28. lineEdit->setPlaceholderText(tr("搜索..."));
  29. treeWidget = new QTreeWidget();
  30. treeWidget->setHeaderHidden(true);
  31. vLayout->addWidget(lineEdit);
  32. vLayout->addWidget(treeWidget);
  33. }
  34. void Widget::initConnection()
  35. {
  36. connect(lineEdit, &QLineEdit::textChanged, this, &Widget::findItem);
  37. }
  38. void Widget::parseJsonRoot()
  39. {
  40. QFile file("F:\\projectCode_yhw\\untitled5\\demo.json");
  41. file.open(QFile::ReadOnly);
  42. QByteArray m_jsonArray = file.readAll();
  43. QJsonParseError jsonError;
  44. QJsonObject jsonObject;
  45. QJsonDocument document = QJsonDocument::fromJson(m_jsonArray, &jsonError);
  46. if (!(document.isNull() || jsonError.error != QJsonParseError::NoError)) {
  47. jsonObject = document.object();
  48. }
  49. QJsonValue value = jsonObject.value("data");
  50. if (!value.isArray()) {
  51. return;
  52. }
  53. QJsonArray array = value.toArray();
  54. int nSize = array.size();
  55. for (int i = 0; i < nSize; i++) {
  56. QJsonObject object = array.at(i).toObject();
  57. if (!(object.contains("text") && object.contains("children"))) {
  58. return;
  59. }
  60. QString itemText = object.value("text").toString();
  61. QJsonArray itemChild = object.value("children").toArray();
  62. QTreeWidgetItem* itemRoot = new QTreeWidgetItem(treeWidget, QStringList(itemText));
  63. treeWidget->addTopLevelItem(itemRoot);
  64. if (itemChild.size() != 0) {
  65. parseArray(itemChild, itemRoot);
  66. }
  67. }
  68. }
  69. /**
  70. * @brief 解析json object, 如果child对应的value为数组,则交给parseArray处理
  71. * @param obj json object对象
  72. * @param itemNode 树节点
  73. */
  74. void Widget::parseObject(const QJsonObject& obj, QTreeWidgetItem* itemNode)
  75. {
  76. if (obj.contains("text") && obj.contains("children")) {
  77. QString itemText = obj.value("text").toString();
  78. QJsonArray itemChild = obj.value("children").toArray();
  79. // 添加子节点
  80. QTreeWidgetItem* item = new QTreeWidgetItem(itemNode, QStringList(itemText));
  81. itemNode->addChild(item);
  82. if (itemChild.size() != 0) {
  83. parseArray(itemChild, item);
  84. }
  85. }
  86. }
  87. /**
  88. * @brief AddVistors::parseArray
  89. * 解析数组, 将数组的每一个值交给ParseObject()函数处理
  90. * @param arr json数组
  91. * @param itemNode 树节点
  92. */
  93. void Widget::parseArray(const QJsonArray& arr, QTreeWidgetItem* itemNode)
  94. {
  95. int size = arr.size();
  96. for (int i = 0; i < size; i++) {
  97. QJsonObject obj = arr.at(i).toObject();
  98. parseObject(obj, itemNode);
  99. }
  100. }
  101. // 查找与text相同的item
  102. void Widget::findItem(const QString& text)
  103. {
  104. treeWidget->collapseAll();
  105. if (text.isEmpty()) {
  106. QTreeWidgetItemIterator it(treeWidget);
  107. while (*it) {
  108. (*it)->setForeground(0, Qt::black);
  109. it++;
  110. }
  111. return;
  112. }
  113. if (!treeWidget->topLevelItemCount()) {
  114. return;
  115. }
  116. QTreeWidgetItemIterator it(treeWidget);
  117. while (*it) {
  118. this->setCursor(Qt::WaitCursor);
  119. QString str = (*it)->text(0);
  120. if (-1 != str.indexOf(text)) {
  121. QTreeWidgetItem* pItem = (*it)->parent();
  122. if (pItem != nullptr) {
  123. bool isExpanded = pItem->isExpanded();
  124. if (!isExpanded) {
  125. treeWidget->expandItem(pItem);
  126. }
  127. }
  128. (*it)->setForeground(0, Qt::red);
  129. parentExpand(*it);
  130. } else {
  131. (*it)->setForeground(0, Qt::black);
  132. }
  133. it++;
  134. }
  135. this->setCursor(Qt::ArrowCursor);
  136. }
  137. // 递归展开指定的节点的parent
  138. void Widget::parentExpand(QTreeWidgetItem* item)
  139. {
  140. if (item->parent() != nullptr) {
  141. QTreeWidgetItem* pItem = item->parent();
  142. if (!pItem->isExpanded()) {
  143. pItem->setExpanded(true);
  144. }
  145. parentExpand(pItem);
  146. }
  147. }

main函数

  1. #include "widget.h"
  2. #include <QApplication>
  3. int main(int argc, char *argv[])
  4. {
  5. QApplication a(argc, argv);
  6. Widget w;
  7. w.show();
  8. return a.exec();
  9. }