2.1 Slate 基础:控件、槽位与声明式语法
三个核心概念
- 控件(Widget):SWidget 派生类。SButton、STextBlock、SListView 等都是。控件本身是「不可变」的——创建后通过参数设属性,不保留可变状态(状态变化靠重新构造或坏 revolves)
- 槽位(Slot):容器控件(SVerticalBox、SHorizontalBox、SOverlay)的「子节点包装」。每个子控件都必须装在一个槽位里。槽位携带布局信息(Padding、对齐、占比)。
- 属性(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 最不习惯的一点。
常见错误
- 忘了
[]:槽位的内容必须包在中括号里,写成SNew(SButton) SNew(STextBlock)是编译错误。 - SNew 后想改属性:Slate 控件创建后大部分属性不可直接改(要么用绑定,要么重建)。少数控件(STextBlock::SetText)提供 setter,但不保证重绘时机。
- 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)也值得照着敲一遍。
