2.1 Slate 基础:控件、槽位与声明式语法

三个核心概念

  1. 控件(Widget):SWidget 派生类。SButton、STextBlock、SListView 等都是。控件本身是「不可变」的——创建后通过参数设属性,不保留可变状态(状态变化靠重新构造或坏 revolves)
  2. 槽位(Slot):容器控件(SVerticalBox、SHorizontalBox、SOverlay)的「子节点包装」。每个子控件都必须装在一个槽位里。槽位携带布局信息(Padding、对齐、占比)。
  3. 属性(Argument):创建时的参数(.Text(...)、.OnClicked(...))。Slate 用「参数声明 + 链式调用」的方式描述界面。

Hello Slate

TSharedRef<SWidget> MyWidget = SNew(SVerticalBox)
    + SVerticalBox::Slot()
    .AutoHeight()
    .Padding(8.0f)
    [
        SNew(STextBlock)
        .Text(FText::FromString(TEXT("你好,Slate")))
    ]
    + SVerticalBox::Slot()
    .FillHeight(1.0f)
    [
        SNew(SButton)
        .Text(FText::FromString(TEXT("点击我")))
        .OnClicked_Lambda([]()
        {
            UE_LOG(LogTemp, Warning, TEXT("按钮被点了"));
            return FReply::Handled();
        })
    ];

读法:

  • SNew(SVerticalBox):创建容器
  • + SVerticalBox::Slot():加一个槽位
  • .AutoHeight() / .FillHeight(1.0f):槽位的高度策略
  • [ ... ]:槽位里装什么(一个控件)
  • .Text(...) / .OnClicked(...):控件参数

整个表达式的类型是 TSharedRef<SWidget>,可以嵌进任何槽位——Slate 的「组合性」就来自这种随处可嵌的结构。

对应 UMG 的心智地图

UMG Slate
垂直/水平框(Vertical/Horizontal Box) SVerticalBox / SHorizontalBox
画布(Canvas Panel) SCanvas 或 SConstraintCanvas
覆盖层(Overlay) SOverlay
文本块 STextBlock
按钮 SButton
复选框 SCheckBox
列表视图 SListView / SListView<T>,需要 ItemHeight + 虚拟化
输入框 SEditableTextBox
滚动条 SScrollBox

属性绑定的两种方式

属性可以是「常量值」也可以是「动态绑定」:

// 常量
SNew(STextBlock).Text(FText::FromString(TEXT("静态")));

// 动态绑定(每次重绘时调函数取最新值)
SNew(STextBlock).Text_Lambda([]() { return FText::FromString(CurrentLabel()); });

// 或 TAttribute
SNew(STextBlock).Text(TAttribute<FText>::Create(&FMyTool::GetLabel));

用绑定而不是「先拿到控件指针再 SetText」——Slate 设计哲学是「属性来源重绘时自取」,手动 SetText 需要持有 TSharedPtr 并手动管刷新时机,容易漏。这是 UMG 玩家转 Slate 最不习惯的一点。

常见错误

  1. 忘了 [ ]:槽位的内容必须包在中括号里,写成 SNew(SButton) SNew(STextBlock) 是编译错误。
  2. SNew 后想改属性:Slate 控件创建后大部分属性不可直接改(要么用绑定,要么重建)。少数控件(STextBlock::SetText)提供 setter,但不保证重绘时机。
  3. lambda 返回值:OnClicked 要返回 FReply::Handled() 或 FReply::Unhandled(),返回普通 void 会编译报错。

心得:学 Slate 最有效的方式是「抄编辑器」:打开控件反射器(下下节),对编辑器里任意面板「Enable Widget Reflector」,Hover 到控件上,反射器会显示它的类、属性、层级。编辑器本身就是最大的 Slate 示例库——官方文档「Slate 控件示例」(https://www.wanxiangyundang.top/read/unreal-engine-5-8-docs/slate-ui-widget-examples-for-u-43ef)也值得照着敲一遍。