从 QTreeView 或 QTreeWidget 制作树文件夹

问题描述 投票:0回答:2

从 Rest API 读取文件夹树,然后将它们显示给用户

调用 API 后的 json 响应示例:

[
{"name":"/folder1/file1.txt";"size":"1KB"},
{"name":"/folder1/file2.txt";"size":"1KB"},
{"name":"/folder1/sub/file3.txt";"size":"1KB"},
{"name":"/folder2/file4.txt";"size":"1KB"},
{"name":"/folder2/file5.txt";"size":"1KB"}
]

我只想制作如下图所示的 GUI:

2个选项:

  1. QTreeView

  2. QTreeWidget

在这张照片中,我使用了 QTreeWidget(带有静态数据)。 目前,我不知道为此建立数据模型。

我制作了TreeModel来为QtreeView设置数据。 但是当它们显示在 GUI 中时,所有数据仅显示在名称列中。 我从http://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html

复制了代码

但是现在我无法解决这个问题。我需要一个示例源代码。 另外,我也只想简单地显示树视图。

不要使用 QFileSystem,因为数据是从 Rest API 获取的。

qt treeview qtreeview qtreewidget qtreewidgetitem
2个回答
3
投票

你要做的就是通过获取文件的名称和大小来解析json,然后使用“/”分隔名称,并以适当的方式将其添加到模型中。

#include <QApplication>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QStandardItemModel>
#include <QTreeView>
#include <QFileIconProvider>

QStandardItem * findChilItem(QStandardItem *it, const QString & text){
    if(!it->hasChildren())
        return nullptr;
    for(int i=0; i< it->rowCount(); i++){
        if(it->child(i)->text() == text)
            return it->child(i);
    }
    return nullptr;
}

static void appendToModel(QStandardItemModel *model, const QStringList & list, const QString & size){
    QStandardItem *parent = model->invisibleRootItem();
    QFileIconProvider provider;

    for(QStringList::const_iterator it = list.begin(); it != list.end(); ++it)
    {
        QStandardItem *item = findChilItem(parent, *it);
        if(item){
            parent = item;
            continue;
        }
        item = new QStandardItem(*it);
        if(std::next(it) == list.end()){
            item->setIcon(provider.icon(QFileIconProvider::File));
            parent->appendRow({item, new QStandardItem(size)});
        }
        else{
            item->setIcon(provider.icon(QFileIconProvider::Folder));
            parent->appendRow(item);
        }
        parent = item;
    }
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QStandardItemModel model;
    model.setHorizontalHeaderLabels({"Name", "Size"});
    const std::string json = R"([
                             {"name":"/folder1/file1.txt";"size":"1KB"},
                             {"name":"/folder1/file2.txt";"size":"1KB"},
                             {"name":"/folder1/sub/file3.txt";"size":"1KB"},
                             {"name":"/folder2/file4.txt";"size":"1KB"},
                             {"name":"/folder2/file5.txt";"size":"1KB"}
                             ])";

    QJsonParseError parse;
    // The string is not a valid json, the separator must be a comma
    // and not a semicolon, which is why it is being replaced
    QByteArray data = QByteArray::fromStdString(json).replace(";", ",");
    QJsonDocument const& jdoc =  QJsonDocument::fromJson(data, &parse);
    Q_ASSERT(parse.error == QJsonParseError::NoError);
    if(jdoc.isArray()){
        for(const QJsonValue &element : jdoc.array() ){
            QJsonObject obj = element.toObject();
            QString name = obj["name"].toString();
            QString size = obj["size"].toString();
            appendToModel(&model, name.split("/", QString::SkipEmptyParts), size);
        }
    }

    QTreeView view;
    view.setModel(&model);
    view.show();
    return a.exec();
}

注意:分号不是 json 的有效分隔符,所以我必须更改它。


0
投票

或者在 python pyqt5 中你可以这样编码:

import sys
from PyQt5 import QtGui, QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow, QTreeView, QVBoxLayout, QWidget

class TreeViewExample(QMainWindow):

    def __init__(self):
        super().__init__()

        self.setWindowTitle("QTreeView Example")
        self.setGeometry(100, 100, 800, 600)

        self.central_widget = QWidget(self)
        self.setCentralWidget(self.central_widget)

        self.tree_view = QTreeView(self.central_widget)
        self.model = QtGui.QStandardItemModel()
        self.tree_view.setModel(self.model)

        # Set up the layout
        layout = QVBoxLayout(self.central_widget)
        layout.addWidget(self.tree_view)

        # Replace this list with your own list of file paths
        file_paths = [
            "/home/user/documents/file1.txt",
            "/home/user/documents/folder1/file2.txt",
            "/home/user/documents/folder1/file3.txt",
            "/home/user/pictures/photo1.jpg",
            "/home/user/pictures/folder2/photo2.jpg",
        ]

        # Organize file paths in parent-child hierarchy
        self.organize_paths(file_paths)
        self.tree_view.clicked.connect(self.on_item_clicked)

        

    def on_item_clicked(self, index):
        # Get the item from the index
        item = self.model.itemFromIndex(index)

        # Get the parent paths recursively
        parent_paths = []
        while item:
            parent_paths.insert(0, item.text())
            item = item.parent()
        print("Parent Paths:", "/".join(parent_paths))


    def organize_paths(self, file_paths):
        for path in file_paths:
            components = path.split("/")[1:]
            current_parent = None

            for component in components:
                #print('component:', component)
                item = self.get_or_create_item(component, parent=current_parent)
                current_parent = item


    def get_or_create_item(self, text, parent=None):

        if parent:
            #print('add to parent:', text, parent)
            item = None
            
            # find item
            for row in range(parent.rowCount()):
                child = parent.child(row)
                #print('>> child:', child.text())
                if child.text() == text:
                    item = child
                    break
                
            if item:
                #print('  parent return:', item)
                return item
            else:
                item = QtGui.QStandardItem(text)
                #print('  parent create:', text)
                parent.appendRow(item)
                #print('  parent create:', text, item)
                return item
        else:
            #print('add to model:', text)
            items = self.model.findItems(text)
            
            if items:
                #print('  model return:', items[0])
                return items[0]
            else:
                item = QtGui.QStandardItem(text)
                self.model.appendRow(item)
                #print('  model create:', text, item)
                return item

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = TreeViewExample()
    window.show()
    sys.exit(app.exec())



© www.soinside.com 2019 - 2024. All rights reserved.