• Qt6 使用 QTreeWidget 控件输出进程树


    一、使用 QTreeWidget 控件输出进程树

    1. void TaskMgrQt::InitTreeWidget()
    2. {
    3. ui.treeWidget->header()->setVisible(false);
    4. ui.treeWidget->setAttribute(Qt::WA_DeleteOnClose); // QWidget 及其 派生类的对象 自动内存清理
    5. }
    6. // 进程结构体
    7. struct Process {
    8. int pid; // 进程ID
    9. int ppid; // 父进程ID
    10. QString name; // 进程名称
    11. std::vector children; // 子进程数组
    12. Process(int pid, int ppid, QString name) : pid(pid), ppid(ppid), name(name) {}
    13. };
    14. // 构建进程树
    15. void buildProcessTree(const std::vectorint, int, QString>>& processes, std::vector& roots) {
    16. std::vector().swap(roots);
    17. std::unordered_map<int, Process*> processMap;
    18. // 创建所有进程节点
    19. for (const auto& p : processes) {
    20. Process* proc = new Process(std::get<0>(p), std::get<1>(p), std::get<2>(p));
    21. processMap.emplace(proc->pid, proc); // 添加
    22. }
    23. // 将进程组织成树形结构
    24. for (auto& pair : processMap) {
    25. Process* proc = pair.second;
    26. if (proc->pid == 0)
    27. {
    28. roots.push_back(proc);
    29. }
    30. else
    31. {
    32. auto iter = processMap.find(proc->ppid);
    33. if (iter != processMap.end())
    34. {
    35. Process* parent = iter->second;
    36. if (parent) {
    37. parent->children.push_back(proc);
    38. }
    39. }
    40. else
    41. {
    42. // 顶层进程,父进程已经终止
    43. roots.push_back(proc);
    44. }
    45. }
    46. }
    47. }
    48. // 递归填充QTreeWidget
    49. void fillTreeWidget(QTreeWidget* treeWidget, QTreeWidgetItem* parentItem, Process* process) {
    50. // 创建当前进程节点
    51. QTreeWidgetItem* item;
    52. if (parentItem == NULL)
    53. {
    54. item = new QTreeWidgetItem(treeWidget);
    55. item->setText(0, QString("%1: %2").arg(process->pid).arg(process->name));
    56. treeWidget->addTopLevelItem(item);
    57. }
    58. else
    59. {
    60. item = new QTreeWidgetItem(parentItem);
    61. item->setText(0, QString("%1: %2").arg(process->pid).arg(process->name));
    62. }
    63. if (process->children.size() > 0)
    64. item->setExpanded(true);
    65. // 递归填充子进程节点
    66. for (Process* child : process->children) {
    67. fillTreeWidget(treeWidget, item, child);
    68. }
    69. }
    70. void TaskMgrQt::slot_onRefresh(... ...)
    71. {
    72. ... ...
    73. // 清理树控件
    74. ui.treeWidget->clear();
    75. // 生成树控件
    76. std::vectorint, int, QString>> processes;
    77. for (int i = 0; i < info.list.size();)
    78. {
    79. QString qstrProcName = Ansi2Unicode(info.list[i], m_nCodePage);
    80. i++;
    81. std::string strPid = info.list[i];
    82. i++;
    83. std::string strPPID = info.list[i];
    84. i++;
    85. std::string strIs32 = info.list[i];
    86. i++;
    87. int nPid = atoi(strPid.c_str());
    88. int nPPid = atoi(strPPID.c_str());
    89. processes.push_back(std::make_tuple(nPid, nPPid, qstrProcName));
    90. }
    91. std::vector roots;
    92. buildProcessTree(processes, roots);
    93. // 填充 树控件
    94. for (int i = 0; i < roots.size(); i++)
    95. {
    96. fillTreeWidget(ui.treeWidget, NULL, roots[i]);
    97. }
    98. ... ...
    99. }

    二、通过 树控件 中 的 进程 PID 定位到 表格控件中的 进程PID

    1. void TaskMgrQt::slot_onTreeItemClick(QTreeWidgetItem* item, int column)
    2. {
    3. QString qstrItemText = item->text(column);
    4. QStringList qstrList = qstrItemText.split(":");
    5. QString qstrPid = qstrList[0].trimmed();
    6. for (int i = 0; i < ui.tableWidget->rowCount(); i++)
    7. {
    8. QString temp = ui.tableWidget->item(i, 1)->text().trimmed();
    9. if (temp == qstrPid)
    10. {
    11. ui.tableWidget->selectRow(i);
    12. break;
    13. }
    14. }
    15. }

    三、通过 表格控件中的进程PID 定位到 树控件中的进程PID

    1. void SearchTreeWidget(QTreeWidget* treeWidget, QTreeWidgetItem* parentItem, QString qstrPid)
    2. {
    3. // 获取当前进程结点
    4. QString qstrTemp = parentItem->text(0).trimmed();
    5. QStringList qstrList = qstrTemp.split(":");
    6. QString qstrTempPid = qstrList[0].trimmed();
    7. if (qstrTempPid == qstrPid)
    8. {
    9. // 已遍历到 指定进程
    10. treeWidget->clearSelection(); // 清除之前的选择
    11. parentItem->setSelected(true); // 选中该项目
    12. treeWidget->scrollToItem(parentItem); // 确保选中项目可见
    13. }
    14. for (int i = 0; i < parentItem->childCount(); i++)
    15. {
    16. QTreeWidgetItem* item = parentItem->child(i);
    17. SearchTreeWidget(treeWidget, item, qstrPid);
    18. }
    19. }
    20. void TaskMgrQt::slot_onTableItemClick(QTableWidgetItem* item)
    21. {
    22. QString qstrPid = ui.tableWidget->item(item->row(), 1)->text().trimmed();
    23. for (int i = 0; i < ui.treeWidget->topLevelItemCount(); i++)
    24. {
    25. QTreeWidgetItem* item = ui.treeWidget->topLevelItem(i);
    26. SearchTreeWidget(ui.treeWidget, item, qstrPid);
    27. }
    28. }

    注意:

    在 进程树 和 进程表格 两个控件中,控件中的行数是相同的,也就是说 “控件中的行数是所有进程数目总和”。

  • 相关阅读:
    社区系统项目复盘-2
    PUBG官方:聊聊外挂、封号、误封、白名单等问题
    国外问卷调查赚钱靠谱吗?
    1965. 丢失信息的雇员
    vue2 checkbox问题
    springboot+新冠疫苗预约管理系统 毕业设计-附源码241530
    Vue-CLI项目搭建
    MIR7创建预制发票BAPI
    COIN++: Neural Compression Across Modalities 论文阅读笔记
    【中鸡前端+Vue面试精选】
  • 原文地址:https://blog.csdn.net/BlackNight168/article/details/136316203