可以根据文件夹列表生成节点行 UI,核心是通过 递归遍历文件夹结构 构建树形节点数据,再关联到 TreeView 的生成逻辑中。以下是具体实现方案,保持原有 TreeView 框架不变,仅修改数据初始化和节点生成部分:
1. 新增文件夹遍历工具函数(用于构建节点数据)
在.cpp
文件中添加递归遍历文件夹的函数,将文件夹结构转换为FDynamicTreeNode
树形结构:
cpp
运行
// 递归遍历文件夹,生成树形节点
void SDynamicTreeViewWidget::AddFolderToNode(const FString& FolderPath, TSharedPtr<FDynamicTreeNode> ParentNode)
{
if (!FPaths::DirectoryExists(FolderPath))
return;
// 获取当前文件夹名称(作为节点名称)
FString FolderName = FPaths::GetCleanFilename(FolderPath);
TSharedPtr<FDynamicTreeNode> CurrentNode = MakeShareable(new FDynamicTreeNode(FolderName, ParentNode));
if (ParentNode.IsValid())
{
ParentNode->Children.Add(CurrentNode); // 作为子节点添加
}
else
{
RootNodes.Add(CurrentNode); // 作为根节点添加
}
// 遍历子文件夹
TArray<FString> SubFolders;
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
FDirectoryVisitor Visitor = FDirectoryVisitor::CreateLambda([&](const TCHAR* Path, bool bIsDirectory)
{
if (bIsDirectory && Path != FolderPath) // 只处理子文件夹(排除当前文件夹)
{
SubFolders.Add(Path);
return true; // 继续遍历
}
return true;
});
PlatformFile.IterateDirectory(*FolderPath, Visitor);
// 递归处理子文件夹
for (const FString& SubFolder : SubFolders)
{
AddFolderToNode(SubFolder, CurrentNode);
}
}
2. 修改节点初始化方法(从文件夹列表生成)
将原InitRootNodes
改为从目标文件夹路径初始化:
cpp
运行
void SDynamicTreeViewWidget::InitRootNodes()
{
RootNodes.Empty();
// 目标文件夹路径(可替换为你的文件夹路径,支持多个根文件夹)
TArray<FString> RootFolderPaths = {
FPaths::ProjectContentDir() + TEXT("YourFolder1"), // 项目Content下的文件夹1
FPaths::ProjectDir() + TEXT("YourFolder2") // 项目根目录下的文件夹2
};
// 遍历所有根文件夹,生成节点
for (const FString& RootFolder : RootFolderPaths)
{
AddFolderToNode(RootFolder, nullptr); // 第二个参数为nullptr表示添加为根节点
}
}
3. 保持 UI 生成逻辑不变(自动适配文件夹节点)
原OnGenerateTreeRow
和OnGetChildren
无需修改,会自动根据文件夹生成的节点数据显示层级结构:
cpp
运行
// 生成节点行UI(无需修改,自动显示文件夹名称)
TSharedRef<ITableRow> SDynamicTreeViewWidget::OnGenerateTreeRow(
TSharedPtr<FDynamicTreeNode> InItem,
const TSharedRef<STableViewBase>& OwnerTable
)
{
return SNew(STableRow<TSharedPtr<FDynamicTreeNode>>, OwnerTable)
.Content()
[
SNew(STextBlock)
.Text(FText::FromString(InItem->NodeName)) // 显示文件夹名称
.Font(FSlateFontInfo(TEXT("C:/Windows/Fonts/msyh.ttc"), 14))
.Margin(FMargin(4.0f * InItem->GetDepth(), 4.0f)) // 按层级缩进
];
}
// 获取子节点(无需修改,自动返回子文件夹节点)
void SDynamicTreeViewWidget::OnGetTreeChildren(
TSharedPtr<FDynamicTreeNode> InItem,
TArray<TSharedPtr<FDynamicTreeNode>>& OutChildren
)
{
if (InItem.IsValid())
{
OutChildren = InItem->Children; // 子文件夹节点
}
}
4. 核心逻辑说明
-
文件夹遍历:
通过IPlatformFile
递归遍历指定文件夹路径,获取所有子文件夹,每级文件夹对应一个FDynamicTreeNode
节点。 -
节点结构映射:
- 根文件夹 → TreeView 根节点
- 子文件夹 → 对应父节点的子节点
- 文件夹名称 → 节点显示文本
-
UI 自动适配:
原 TreeView 的 UI 生成逻辑(OnGenerateTreeRow
)会根据节点的NodeName
(文件夹名)和GetDepth
(层级深度)自动显示缩进和文本,无需额外修改。
5. 使用方法
- 替换
RootFolderPaths
中的路径为你的目标文件夹(支持绝对路径或 UE 路径宏,如FPaths::ProjectContentDir()
); - 编译后,TreeView 会自动显示文件夹的层级结构,点击节点前的箭头可展开 / 折叠子文件夹。
扩展优化(可选)
- 显示文件夹图标:在
STextBlock
前添加SImage
,使用 UE 内置文件夹图标(FEditorStyle::Get().GetBrush("ContentBrowser.FolderIcon")
); - 过滤特定文件夹:在
AddFolderToNode
中添加判断,跳过不需要显示的文件夹(如.git
、Binaries
等); - 支持文件显示:修改遍历逻辑,同时获取文件,用不同节点类型区分文件夹和文件(添加
bIsFile
标志)。
通过以上修改,TreeView 会完全根据文件夹列表动态生成节点 UI,保持原有交互逻辑的同时实现文件夹结构可视化。