从 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"}
]
有2个选项:
QTreeView
QTreeWidget
在这张照片中,我使用了 QTreeWidget(带有静态数据)。 目前,我不知道为此建立数据模型。
我制作了TreeModel来为QtreeView设置数据。 但是当它们显示在 GUI 中时,所有数据仅显示在名称列中。 我从http://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html
复制了代码但是现在我无法解决这个问题。我需要一个示例源代码。 另外,我也只想简单地显示树视图。
不要使用 QFileSystem,因为数据是从 Rest API 获取的。
你要做的就是通过获取文件的名称和大小来解析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 的有效分隔符,所以我必须更改它。
或者在 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())