如何在鼠标单击时获取 QTreeWidget 中当前选定项的绝对路径

How to Get Absolute Path of Currently Selected Item in QTreeWidget on mouse Clicked

我有一个简单的QTreeWidget指向根目录:

#include <QTreeWidget>
#include <QStringList>
#include <QApplication>

int main(int argc, char **argv)
{
QApplication application(argc, argv);
QStringList fileNames{"TEST/branch", "trunk"};
QTreeWidget treeWidget;
treeWidget.setColumnCount(1);

for (const auto& filename : fileNames) 
{
    QTreeWidgetItem *parentTreeItem = new QTreeWidgetItem(&treeWidget);
    parentTreeItem->setText(0, filename.split('/').first());
    QStringList filenameParts = filename.split('/').mid(1);

    for(const auto& filenamePart : filenameParts) 
    {
         QTreeWidgetItem *treeItem = new QTreeWidgetItem();
         treeItem->setText(0, filenamePart);
         parentTreeItem->addChild(treeItem);
         parentTreeItem = treeItem;
    }
}

treeWidget.show();
return application.exec();
}

输出:

我在上面选择的项目是/TEST/branches。如何获取当前选中项的绝对路径?

好吧,我认为没有内置函数可以做到这一点,但您可以自己编写一个函数,例如

QString treeItemToFullPath(QTreeWidgetItem* treeItem)
{
    QString fullPath= treeItem->text(0);

    while (treeItem->parent() != NULL)
    {
        fullPath= treeItem->parent()->text(0) + "/" + fullPath;
        treeItem = treeItem->parent();
    }
    return fullPath;
}

编辑: 输入 treeItem 是要显示其路径的选定树项。如果您确定至少选择了一项,则可以通过

获取
treeWidget.selectedItems().first();

另一种方法是使用工具提示。您可以为每个项目添加提示,同时将它们添加到树中,但您可以在将它们添加到最终位置后执行此操作。

改变这个

for(const auto& filenamePart : filenameParts) 
{
     QTreeWidgetItem *treeItem = new QTreeWidgetItem();
     treeItem->setText(0, filenamePart);
     parentTreeItem->addChild(treeItem);
     parentTreeItem = treeItem;
}

这样

for(const auto& filenamePart : filenameParts) 
{
     QTreeWidgetItem *treeItem = new QTreeWidgetItem();
     treeItem->setText(0, filenamePart);
     parentTreeItem->addChild(treeItem);
     parentTreeItem = treeItem;
     treeItem->setToolTip(0, treeItemToFullPath(treeItem));
}

这样,只要将鼠标悬停在项目上,您就会看到完整路径。

要获得当前项目更改的通知,可以使用 QTreeWidget::currentItemChangedQItemSelectionModel::currentChanged

获取完整路径主要有两种方式:

  1. 从所选项目开始迭代树并重建路径。这使数据模型保持规范化 - 没有冗余信息。

  2. 存储每个项目的完整路径。

如果树很大,存储规范化的模型将使用较少的内存。鉴于项目的选择可能很少见,因为它是根据明确的用户输入完成的,因此迭代树以提取完整路径的成本是微不足道的。在按下按键或鼠标按钮时,人类并不是那么快。

该示例演示了两种方法:

// https://github.com/KubaO/Whosebugn/tree/master/questions/tree-path-41037995
#include <QtWidgets>

QTreeWidgetItem *get(QTreeWidgetItem *parent, const QString &text) {
   for (int i = 0; i < parent->childCount(); ++i) {
      auto child = parent->child(i);
      if (child->text(0) == text)
         return child;
   }
   return new QTreeWidgetItem(parent, {text});
}

int main(int argc, char **argv)
{
   QApplication app(argc, argv);
   QStringList filenames{"TEST/branch", "TEST/foo", "trunk"};
   QWidget window;
   QVBoxLayout layout(&window);
   QTreeWidget treeWidget;
   QLabel label1, label2;

   for (const auto &filename : filenames) {
      QString path;
      auto item = treeWidget.invisibleRootItem();
      for (auto const &chunk : filename.split('/')) {
         item = get(item, chunk);
         path.append(QStringLiteral("/%1").arg(chunk));
         item->setData(0, Qt::UserRole, path);
      }
   }

   QObject::connect(&treeWidget, &QTreeWidget::currentItemChanged, [&](const QTreeWidgetItem *item){
      QString path;
      for (; item; item = item->parent())
         path.prepend(QStringLiteral("/%1").arg(item->text(0)));
      label1.setText(path);
   });

   QObject::connect(&treeWidget, &QTreeWidget::currentItemChanged, [&](const QTreeWidgetItem *item){
      label2.setText(item->data(0, Qt::UserRole).toString());
   });

   layout.addWidget(&treeWidget);
   layout.addWidget(&label1);
   layout.addWidget(&label2);
   window.show();
   return app.exec();
}