【UE工具向】如何优雅的扩展DataTable ToolBar

如何优雅的向DataTable上方ToolBar区域新增功能按钮

近期终于抽出空来把之前做的一些小东西整理出来,希望能对你有帮助。引擎版本5.4

  • 问题背景:只要是大量使用DT的项目我想都会遇到想要"一键处理XXX"的需求,比如是一键打开表格配置的蓝图,一键运行表格配置合法性检查等等。问题随之而来,如何优雅的扩展增加按钮,总不能是来个需求都往引擎源码里加,这有点痛苦,而且还要求对如何扩展引擎编辑器有基本的了解。

基础思路

  • 朴素的想法是不同表格有不同的需求,那么最好按钮由每张表格自己决定
  • 最好加按钮的人不需要了解引擎如何扩展,不需要改引擎代码,只在对应表格代码中处理相关逻辑

说干就干

  • 引擎中新增一个扩展按钮信息结构体

    // 在DataTable.h新增
    USTRUCT(BlueprintType)
    struct FDTExtendToolBarBtnInfo
    {
        GENERATED_BODY()
    public:
        FDTExtendToolBarBtnInfo() = default;
        FDTExtendToolBarBtnInfo(FString InLabel, FString InFuncType, FString InToolTip)
            : Label(InLabel)
            , FuncType(InFuncType)
            , ToolTip(InToolTip)
        {
        }
        bool operator==(const FDTExtendToolBarBtnInfo& Other) const
        {
            return Label == Other.Label && FuncType == Other.FuncType;
        }
        UPROPERTY()
        FString Label = "TestExtendBtn";
        UPROPERTY()
        FString FuncType = "Test";
        UPROPERTY()
        FString ToolTip = "ToolBar tool tip";
        UPROPERTY()
        FString IconStyleSet = "EditorStyle";
        UPROPERTY()
        FString IconStyle = "ContentBrowser.ImportPackage";
    };
    
  • 从 GetLifetimeReplicatedProps() 得到灵感,在TableRowBase表行基类结构体中增加虚函数,从子类表行中获取要增加的扩展按钮信息

    // DataTable.h中 FTableRowBase 中增加虚函数
    #if WITH_EDITOR
    // 这里新增虚函数,由子类各自塞入扩展信息
    virtual void GetExtendToolBars(TArray<FDTExtendToolBarBtnInfo>& OutExtendToolBars) { };
    // 按钮回调事件
    virtual void OnExtendToolBarBtnClicked(const FString InBtnType) { };
    #endif // WITH_EDITOR
    
  • 由DataTableEditor获取到之后统一注册扩展,绑定回调函数到对应的表行,去执行不同的处理逻辑

    // DataTable.h中 FDataTableEditor::FillToolbar(FToolBarBuilder& ToolbarBuilder)函数中统一注册增加当前表格的扩展按钮
    // 自定义增加ToolBar按钮
    ToolbarBuilder.BeginSection("CustomDTCommands");
    {
        const UDataTable* ViewTable = GetDataTable();
        if (ViewTable && HighlightedRowName.IsValid())
        {
            auto RowData = ViewTable->FindRow<FTableRowBase>(HighlightedRowName, "");
            if (!RowData)
            {
                return;
            }
            TArray<FDTExtendToolBarBtnInfo> ExtendBtnInfos;
            RowData->GetExtendToolBars(ExtendBtnInfos); // 从子类获取
            for (const auto& BtnInfo : ExtendBtnInfos)
            {
                FString FuncType = BtnInfo.FuncType;
                ToolbarBuilder.AddToolBarButton(
                    FUIAction(FExecuteAction::CreateLambda([this, FuncType]() {
                        const UDataTable* ViewTable = GetDataTable();
                        if (ViewTable && HighlightedRowName.IsValid())
                        {
                            auto RowData = ViewTable->FindRow<FTableRowBase>(HighlightedRowName, "");
                            if (RowData)
                            {
                                RowData->OnExtendToolBarBtnClicked(FuncType); // 回调到子类
                            }
                        }
                    })),
                    NAME_None,
                    TAttribute(FText::FromString(BtnInfo.Label)),
                    TAttribute(FText::FromString(BtnInfo.ToolTip)),
                    FSlateIcon(FName(BtnInfo.IconStyleSet), FName(BtnInfo.IconStyle))
                );
            }
        }
    }
    ToolbarBuilder.EndSection();
    

    牛刀小试

    • 我们随意找一个表行结构体来试验,扩展一个按钮仅需要几行代码,添加按钮的代码是简单而固定的。对于执行同学来说,只需要关注回调函数中自己的处理逻辑即可。
      img
      img
    • 引擎内效果
      img
posted @ 2025-11-03 00:13  yocichen  阅读(10)  评论(0)    收藏  举报