目录
- [0 引言](#0 引言)
- [1 Slate框架](#1 Slate框架)
-
- [1.0 控件布局](#1.0 控件布局)
- [1.1 SWidget](#1.1 SWidget)
-
- [1.1.1 SWidget的主要作用](#1.1.1 SWidget的主要作用)
- [1.1.2 SWidget的关键方法](#1.1.2 SWidget的关键方法)
- [1.1.3 使用SWidget创建自定义控件](#1.1.3 使用SWidget创建自定义控件)
- [1.1.4 结论](#1.1.4 结论)
- [1.2 SCompoundWidget](#1.2 SCompoundWidget)
-
- [1.2.1 SCompoundWidget的主要作用](#1.2.1 SCompoundWidget的主要作用)
- [1.2.2 SCompoundWidget的使用示例](#1.2.2 SCompoundWidget的使用示例)
- [1.2.3 SCompoundWidget的关系](#1.2.3 SCompoundWidget的关系)
- [1.2.4 总结](#1.2.4 总结)
- [1.3 SLeafWidget](#1.3 SLeafWidget)
- [1.4 SPanel](#1.4 SPanel)
-
- [1.4.1 SPanel的作用](#1.4.1 SPanel的作用)
- [1.4.2 使用方法](#1.4.2 使用方法)
- [1.4.3 总结](#1.4.3 总结)
- [1.5 STextBlock](#1.5 STextBlock)
-
- [1.5.1 STextBlock的作用](#1.5.1 STextBlock的作用)
- [1.5.2 使用方法](#1.5.2 使用方法)
- [1.5.3 总结](#1.5.3 总结)
- [1.6 SButton](#1.6 SButton)
-
- [1.6.1 SButton的作用](#1.6.1 SButton的作用)
- [1.6.2 使用方法](#1.6.2 使用方法)
- [1.6.3 总结](#1.6.3 总结)
- [1.7 SEditableTextBox](#1.7 SEditableTextBox)
-
- [1.7.1 SEditableTextBox的作用](#1.7.1 SEditableTextBox的作用)
- [1.7.2 使用方法](#1.7.2 使用方法)
- [1.7.3 总结](#1.7.3 总结)
- [1.8 SOverlay](#1.8 SOverlay)
-
- [1.8.1 SOverlay的作用](#1.8.1 SOverlay的作用)
- [1.8.2 使用方法](#1.8.2 使用方法)
- [1.8.3 总结](#1.8.3 总结)
- [1.9 SHorizontalBox、SVerticalBox](#1.9 SHorizontalBox、SVerticalBox)
-
- [1.9.1 SHorizontalBox 和 SVerticalBox 的作用](#1.9.1 SHorizontalBox 和 SVerticalBox 的作用)
- [1.9.2 使用方法](#1.9.2 使用方法)
- [1.9.3 总结](#1.9.3 总结)
- [1.10 SScrollBox](#1.10 SScrollBox)
-
- [1.10.1 SScrollBox的作用](#1.10.1 SScrollBox的作用)
- [1.10.2 使用方法](#1.10.2 使用方法)
- [1.10.3 总结](#1.10.3 总结)
- [2 类之间的关系](#2 类之间的关系)
-
- [2.1 主要类的继承关系和职责](#2.1 主要类的继承关系和职责)
- [2.2 类之间的关系图](#2.2 类之间的关系图)
- [2.3 具体示例和解释](#2.3 具体示例和解释)
- [2.4 总结](#2.4 总结)
- [3 Slate和UMG](#3 Slate和UMG)
-
- [3.1 Slate 和 UMG 的联系](#3.1 Slate 和 UMG 的联系)
- [3.2 Slate 和 UMG 的差异](#3.2 Slate 和 UMG 的差异)
- [3.3 结合使用 Slate 和 UMG](#3.3 结合使用 Slate 和 UMG)
- [3.4 总结](#3.4 总结)
0 引言
项目需要对UE引擎进行二次开发,具体来说是编辑器开发。而Slate知识是进行编辑器开发的基础,这个就是UE中UMG界面开发的C++版本,只不过是通过写代码的方式来进行页面的布局。
1 Slate框架
1.0 控件布局
在Unreal Engine的Slate框架中,Construct
方法是用来初始化控件的。ChildSlot
是一个特殊的插槽,用于指定复合控件(如SCompoundWidget
)的子控件。下面我会详细解释ChildSlot
的作用和使用方法。
ChildSlot的作用
ChildSlot
是复合控件(例如SCompoundWidget
)中的一个插槽,用于容纳单个子控件。通过定义ChildSlot
,你可以将其他Slate控件嵌入到你的自定义控件中。
ChildSlot的使用方法
- 基本用法
ChildSlot
通常出现在Construct
方法中,用于定义控件的布局和内容。以下是一个简单的示例,展示了如何使用ChildSlot
来定义一个文本块控件。
cpp
class SMyWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
// 使用ChildSlot定义控件的内容
ChildSlot
[
SNew(STextBlock)
.Text(FText::FromString("Hello, Slate!"))
];
}
};
在这个示例中,ChildSlot
用于包含一个STextBlock
,它显示文本"Hello, Slate!"。
- 布局和对齐
你可以通过链式调用来设置子控件的布局和对齐方式。例如,可以使用HAlign
和VAlign
属性来设置水平和垂直对齐方式。
cpp
void Construct(const FArguments& InArgs)
{
ChildSlot
.HAlign(HAlign_Center) // 水平居中对齐
.VAlign(VAlign_Center) // 垂直居中对齐
[
SNew(STextBlock)
.Text(FText::FromString("Centered Text"))
];
}
- 复杂布局
你可以在ChildSlot
中嵌套其他复合控件(例如SVerticalBox
和SHorizontalBox
)来创建更复杂的布局。
cpp
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Top Text"))
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Middle Text"))
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Bottom Text"))
]
];
}
在这个示例中,ChildSlot
包含了一个SVerticalBox
,它将三个文本块垂直排列。
以下是一个完整的示例,展示了如何使用ChildSlot
在自定义控件中定义复杂的布局。
cpp
#pragma once
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Layout/SVerticalBox.h"
#include "Widgets/Layout/SHorizontalBox.h"
class SMyComplexWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyComplexWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Top Text"))
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(STextBlock)
.Text(FText::FromString("Left Text"))
]
+ SHorizontalBox::Slot()
.FillWidth(1)
[
SNew(STextBlock)
.Text(FText::FromString("Center Text"))
]
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(STextBlock)
.Text(FText::FromString("Right Text"))
]
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SButton)
.Text(FText::FromString("Click Me"))
.OnClicked(this, &SMyComplexWidget::OnButtonClick)
]
];
}
private:
FReply OnButtonClick()
{
UE_LOG(LogTemp, Warning, TEXT("Button clicked!"));
return FReply::Handled();
}
};
总结
ChildSlot
是SCompoundWidget
中的一个插槽,用于定义控件的内容和布局。通过在Construct
方法中使用ChildSlot
,你可以将其他Slate控件嵌入到你的自定义控件中,并通过链式调用设置对齐和填充属性。了解如何使用ChildSlot
可以帮助你创建复杂且功能丰富的用户界面。
1.1 SWidget
SWidget
是Unreal Engine中Slate框架的基类,所有的UI控件都直接或间接地继承自 SWidget
。SWidget
提供了Slate控件的基本属性和行为,如渲染、事件处理和布局。
1.1.1 SWidget的主要作用
- 基类作用 :
SWidget
是所有Slate控件的基类,定义了控件的基本接口和行为。 - 渲染:管理控件的绘制过程。
- 事件处理:处理用户输入事件,如鼠标点击、键盘输入等。
- 布局管理:管理控件的布局和排列。
- 属性系统:支持Slate的属性绑定和更新机制。
- 状态管理:管理控件的状态,如可见性、启用状态等。
1.1.2 SWidget的关键方法
- 渲染相关方法:
- OnPaint:绘制控件内容的核心方法。
cpp
virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect,
FSlateWindowElementList& OutDrawElements, int32 LayerId,
const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const;
- 布局相关方法
- ComputeDesiredSize:计算控件的理想大小。
cpp
virtual FVector2D ComputeDesiredSize(float LayoutScaleMultiplier) const;
- ArrangeChildren:安排子控件的位置和大小。
cpp
virtual void ArrangeChildren(const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren) const;
- 事件处理相关方法
-
OnMouseButtonDown:处理鼠标按下事件。
cppvirtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent);
-
OnMouseButtonUp:处理鼠标松开事件。
cppvirtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent);
-
OnMouseMove:处理鼠标移动事件。
cppvirtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent);
1.1.3 使用SWidget创建自定义控件
-
创建自定义控件类:继承自
SCompoundWidget
或SLeafWidget
,具体取决于你的控件是否包含子控件。SCompoundWidget
继承自SWidget
并添加了一些额外的功能,如支持包含子控件。 -
实现控件的构造函数和关键方法:以下是一个创建自定义控件的完整示例:
cpp
#pragma once
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Input/SButton.h"
class SMyCustomWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyCustomWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
// 使用ChildSlot定义控件的内容
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Hello, Slate!"))
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SButton)
.Text(FText::FromString("Click Me"))
.OnClicked(this, &SMyCustomWidget::OnButtonClick)
]
];
}
private:
// 按钮点击事件处理函数
FReply OnButtonClick()
{
UE_LOG(LogTemp, Warning, TEXT("Button clicked!"));
return FReply::Handled();
}
};
解释构造函数和方法
- 构造函数:
Construct
方法用于初始化控件。SLATE_BEGIN_ARGS
和SLATE_END_ARGS
宏定义控件的构造参数。
cpp
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Hello, Slate!"))
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SButton)
.Text(FText::FromString("Click Me"))
.OnClicked(this, &SMyCustomWidget::OnButtonClick)
]
];
}
- 事件处理函数:
OnButtonClick
是按钮点击事件的处理函数。使用FReply::Handled()
表示事件已处理。
cpp
FReply OnButtonClick()
{
UE_LOG(LogTemp, Warning, TEXT("Button clicked!"));
return FReply::Handled();
}
自定义控件的使用
将自定义控件添加到UI中,可以通过在父控件或Slate应用程序中创建实例。
cpp
SNew(SMyCustomWidget)
1.1.4 结论
SWidget
是所有Slate控件的基类,提供了控件的基本属性和行为。通过继承 SWidget
及其派生类(如 SCompoundWidget
),你可以创建自定义控件,定义其外观、布局和交互行为。了解 SWidget
的关键方法和如何使用它们,可以帮助你创建复杂且功能丰富的UI控件。
1.2 SCompoundWidget
SCompoundWidget
是Unreal Engine Slate框架中一个非常重要的类,专门用于创建复合控件(Compound Widget)。复合控件是一种可以包含其他控件的UI元素。SCompoundWidget
继承自 SWidget
,并为开发者提供了更加简便的接口来创建和管理复合控件。
1.2.1 SCompoundWidget的主要作用
- 容器控件 :
SCompoundWidget
主要用作容器控件,可以包含一个或多个子控件。 - 简化构造 :提供了简化的构造方法
Construct
,允许使用Declarative Syntax(声明式语法)来定义子控件和布局。 - 复合行为:允许自定义复合控件的行为,如响应用户输入和控制子控件的排列方式。
关键方法和成员
- 构造方法
SCompoundWidget
使用Construct
方法来初始化控件。这与SWidget
不同,SWidget
需要手动实现一些初始化逻辑。
cpp
void Construct(const FArguments& InArgs);
- 子控件的布局
通过ChildSlot
成员,可以使用声明式语法来定义复合控件的子控件和布局。
cpp
TSlotBase<SlotType>& ChildSlot;
1.2.2 SCompoundWidget的使用示例
定义一个自定义控件
头文件(.h):
cpp
#pragma once
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
class SMyCompoundWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyCompoundWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
private:
FReply OnButtonClick();
};
源文件(.cpp):
cpp
#include "SMyCompoundWidget.h"
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Layout/SVerticalBox.h"
void SMyCompoundWidget::Construct(const FArguments& InArgs)
{
// 使用ChildSlot定义控件的内容
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Hello, Slate!"))
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SButton)
.Text(FText::FromString("Click Me"))
.OnClicked(this, &SMyCompoundWidget::OnButtonClick)
]
];
}
FReply SMyCompoundWidget::OnButtonClick()
{
UE_LOG(LogTemp, Warning, TEXT("Button clicked!"));
return FReply::Handled();
}
SLATE_BEGIN_ARGS
和 SLATE_END_ARGS
宏定义了控件的构造参数。SLATE_BEGIN_ARGS
开始定义,SLATE_END_ARGS
结束定义。参数可以包括控件的属性和事件处理程序。
cpp
SLATE_BEGIN_ARGS(SMyCompoundWidget) {}
SLATE_END_ARGS()
Construct
方法用于初始化控件的内容和布局。通过 ChildSlot
成员,使用声明式语法定义子控件。
cpp
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Hello, Slate!"))
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SButton)
.Text(FText::FromString("Click Me"))
.OnClicked(this, &SMyCompoundWidget::OnButtonClick)
]
];
}
事件处理函数:定义事件处理函数来响应用户输入。在这个例子中,当按钮被点击时,会调用 OnButtonClick
方法。
cpp
FReply OnButtonClick()
{
UE_LOG(LogTemp, Warning, TEXT("Button clicked!"));
return FReply::Handled();
}
在项目中使用自定义控件 :要在项目中使用这个自定义控件,可以在Slate应用程序或其他Slate控件中实例化 SMyCompoundWidget
。
cpp
// 假设这是某个Slate Widget的构造函数中
ChildSlot
[
SNew(SMyCompoundWidget)
];
1.2.3 SCompoundWidget的关系
SCompoundWidget
继承自 SWidget
,因此它拥有 SWidget
的所有功能和属性。同时,SCompoundWidget
允许包含子控件,使其成为创建复杂UI布局和自定义控件的理想选择。
关系图
SWidget
└── SCompoundWidget
├── STextBlock
├── SButton
├── SEditableTextBox
└── 自定义复合控件(例如 SMyCompoundWidget)
1.2.4 总结
SCompoundWidget
是Unreal Engine Slate框架中非常重要的类,用于创建复合控件。通过继承 SCompoundWidget
,可以方便地创建包含其他子控件的自定义控件,并使用声明式语法定义控件的布局和行为。了解 SCompoundWidget
的使用方法,有助于开发复杂且功能丰富的用户界面。
1.3 SLeafWidget
SLeafWidget
是Unreal Engine的Slate框架中的一个类,继承自 SWidget
。与 SCompoundWidget
不同,SLeafWidget
是一种叶子控件(Leaf Widget),它不能包含子控件。SLeafWidget
通常用于实现独立的UI元素,这些元素不需要包含其他控件,例如文本块、图像等。
1.4 SPanel
1.4.1 SPanel的作用
SPanel
是Unreal Engine Slate框架中的一个重要类,用于实现布局控件。它的主要作用是管理和排列子控件,作为一个容器控件,提供对其子控件进行布局和绘制的基础设施。
- 布局管理:管理和排列其子控件的位置和大小。
- 容器控件:可以包含多个子控件,提供容器功能。
- 扩展性:允许开发者继承并实现自定义的布局逻辑。
1.4.2 使用方法
要使用 SPanel
,通常需要创建一个继承自 SPanel
的自定义控件,并实现其布局逻辑。以下是一个简化的示例,展示了如何创建一个自定义面板并排列其子控件。
自定义面板类,头文件(.h)
cpp
#pragma once
#include "CoreMinimal.h"
#include "Widgets/SPanel.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
class SMyPanel : public SPanel
{
public:
SLATE_BEGIN_ARGS(SMyPanel) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs);
// 必须实现的方法
virtual void OnArrangeChildren(const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren) const override;
virtual FVector2D ComputeDesiredSize(float LayoutScaleMultiplier) const override;
protected:
// 子控件列表
TPanelChildren<FSlot> Children;
};
源文件(.cpp)
cpp
#include "SMyPanel.h"
void SMyPanel::Construct(const FArguments& InArgs)
{
// 这里可以初始化面板
}
void SMyPanel::OnArrangeChildren(const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren) const
{
// 自定义子控件的排列逻辑
for (int32 SlotIndex = 0; SlotIndex < Children.Num(); ++SlotIndex)
{
const FSlot& Slot = Children[SlotIndex];
// 假设将所有子控件排列在垂直方向
const FVector2D ChildSize = Slot.GetWidget()->GetDesiredSize();
const FVector2D Position(0, SlotIndex * ChildSize.Y);
ArrangedChildren.AddWidget(AllottedGeometry.MakeChild(Slot.GetWidget(), Position, ChildSize));
}
}
FVector2D SMyPanel::ComputeDesiredSize(float LayoutScaleMultiplier) const
{
FVector2D DesiredSize(0, 0);
for (int32 SlotIndex = 0; SlotIndex < Children.Num(); ++SlotIndex)
{
DesiredSize.Y += Children[SlotIndex].GetWidget()->GetDesiredSize().Y;
}
return DesiredSize;
}
使用自定义面板:在Slate UI中使用自定义面板,可以通过声明式语法来添加子控件。
cpp
SNew(SMyPanel)
+ SMyPanel::Slot()
[
SNew(STextBlock).Text(FText::FromString("Child 1"))
]
+ SMyPanel::Slot()
[
SNew(STextBlock).Text(FText::FromString("Child 2"))
]
1.4.3 总结
SPanel
是用于管理和排列子控件的基类,通过继承 SPanel
并实现其方法,开发者可以创建自定义的布局控件。了解 SPanel
的使用方法,可以帮助你实现复杂的UI布局。
1.5 STextBlock
1.5.1 STextBlock的作用
STextBlock
是Unreal Engine Slate框架中的一个基础控件,用于显示文本。它是一个叶子控件(Leaf Widget),意味着它不能包含其他子控件。STextBlock
提供了各种属性和样式选项来控制文本的显示方式,包括字体、颜色、对齐方式等。
- 显示文本:用于在用户界面中显示静态或动态文本。
- 文本样式:支持丰富的文本样式和格式设置选项。
- 绑定和更新:可以绑定到数据源,并动态更新显示的文本内容。
1.5.2 使用方法
创建一个 STextBlock
控件,并设置要显示的文本。
cpp
SNew(STextBlock)
.Text(FText::FromString("Hello, Slate!"))
可以使用各种属性来设置文本的样式,如字体、颜色和对齐方式。
cpp
SNew(STextBlock)
.Text(FText::FromString("Styled Text"))
.Font(FSlateFontInfo("Arial", 24))
.ColorAndOpacity(FSlateColor(FLinearColor::Red))
.Justification(ETextJustify::Center)
可以绑定一个动态属性,当属性值变化时,文本会自动更新。
cpp
TAttribute<FText> DynamicText = TAttribute<FText>::Create(TAttribute<FText>::FGetter::CreateLambda([]() {
return FText::FromString("Dynamic Text: " + FString::FromInt(FMath::Rand()));
}));
SNew(STextBlock)
.Text(DynamicText)
以下是一个完整的示例,展示了如何在Slate应用中使用 STextBlock
控件。
cpp
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Layout/SVerticalBox.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
class SMyWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Hello, Slate!"))
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Styled Text"))
.Font(FSlateFontInfo("Arial", 24))
.ColorAndOpacity(FSlateColor(FLinearColor::Red))
.Justification(ETextJustify::Center)
]
];
}
};
1.5.3 总结
STextBlock
是用于显示文本的基本控件,通过设置其属性,可以控制文本的显示样式。STextBlock
支持绑定动态属性,使得文本内容可以根据数据源的变化自动更新。通过了解和使用 STextBlock
,可以方便地在Slate UI中展示各种格式和样式的文本内容。
1.6 SButton
1.6.1 SButton的作用
SButton
是Unreal Engine Slate框架中的一个重要控件,用于创建按钮。按钮是一个交互式控件,用户可以点击它来触发某些操作或事件。SButton
提供了各种属性和事件处理程序,允许开发者自定义按钮的外观和行为。
- 用户交互:提供一个交互点,用户可以通过点击按钮来触发特定的操作或事件。
- 可定制外观:可以设置按钮的外观样式,如按钮的文本、图片、颜色等。
- 事件处理:支持点击事件和其他交互事件,允许开发者定义按钮点击后的行为。
1.6.2 使用方法
创建一个简单的按钮,并设置按钮上的文本。
cpp
SNew(SButton)
.Text(FText::FromString("Click Me"))
.OnClicked(this, &SMyWidget::OnButtonClick)
可以通过各种属性来自定义按钮的样式,例如按钮的文本、字体、颜色等。
cpp
SNew(SButton)
.Text(FText::FromString("Styled Button"))
.ButtonColorAndOpacity(FLinearColor::Blue)
.ContentPadding(FMargin(10))
使用 OnClicked
属性绑定一个处理函数,该函数将在按钮被点击时调用。
cpp
FReply SMyWidget::OnButtonClick()
{
// 按钮点击后的处理逻辑
UE_LOG(LogTemp, Warning, TEXT("Button clicked!"));
return FReply::Handled();
}
SNew(SButton)
.Text(FText::FromString("Click Me"))
.OnClicked(this, &SMyWidget::OnButtonClick)
以下是一个完整的示例,展示了如何在Slate应用中使用 SButton
控件,并处理按钮点击事件。
cpp
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Layout/SVerticalBox.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
class SMyWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Hello, Slate!"))
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SButton)
.Text(FText::FromString("Click Me"))
.OnClicked(this, &SMyWidget::OnButtonClick)
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SButton)
.Text(FText::FromString("Styled Button"))
.ButtonColorAndOpacity(FLinearColor::Blue)
.ContentPadding(FMargin(10))
.OnClicked(this, &SMyWidget::OnButtonClick)
]
];
}
private:
FReply OnButtonClick()
{
// 按钮点击后的处理逻辑
UE_LOG(LogTemp, Warning, TEXT("Button clicked!"));
return FReply::Handled();
}
};
1.6.3 总结
SButton
是一个用于创建交互式按钮的控件,通过设置其属性,可以自定义按钮的外观和行为。SButton
支持点击事件处理,可以绑定函数来响应用户点击操作。通过了解和使用 SButton
,可以在Slate UI中实现各种交互功能,提供良好的用户体验。
1.7 SEditableTextBox
1.7.1 SEditableTextBox的作用
SEditableTextBox
是Unreal Engine Slate框架中的一个重要控件,用于创建可编辑的文本框。用户可以在文本框中输入和编辑文本。它提供了丰富的属性和事件处理程序,允许开发者自定义文本框的外观和行为,并处理用户输入。
- 用户输入:允许用户在文本框中输入和编辑文本。
- 数据绑定:可以绑定到数据源,并动态更新显示的文本内容。
- 样式定制:支持多种样式设置,如字体、颜色、对齐方式等。
- 事件处理:提供输入事件和其他交互事件,允许开发者定义文本变化后的行为。
1.7.2 使用方法
创建一个简单的可编辑文本框,并设置初始文本。
cpp
SNew(SEditableTextBox)
.Text(FText::FromString("Initial Text"))
可以通过各种属性来自定义文本框的样式,例如字体、颜色、对齐方式等。
cpp
SNew(SEditableTextBox)
.Text(FText::FromString("Styled TextBox"))
.Font(FSlateFontInfo("Arial", 16))
.ForegroundColor(FSlateColor(FLinearColor::White))
.BackgroundColor(FSlateColor(FLinearColor::Black))
使用 OnTextChanged
和 OnTextCommitted
属性绑定事件处理程序,以处理文本变化和提交事件。
cpp
void OnTextChanged(const FText& NewText)
{
// 文本变化后的处理逻辑
UE_LOG(LogTemp, Warning, TEXT("Text changed: %s"), *NewText.ToString());
}
void OnTextCommitted(const FText& NewText, ETextCommit::Type CommitType)
{
// 文本提交后的处理逻辑
UE_LOG(LogTemp, Warning, TEXT("Text committed: %s"), *NewText.ToString());
}
SNew(SEditableTextBox)
.Text(FText::FromString("Enter text..."))
.OnTextChanged(this, &SMyWidget::OnTextChanged)
.OnTextCommitted(this, &SMyWidget::OnTextCommitted)
以下是一个完整的示例,展示了如何在Slate应用中使用 SEditableTextBox
控件,并处理文本变化和提交事件。
cpp
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Input/SEditableTextBox.h"
#include "Widgets/Layout/SVerticalBox.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
class SMyWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Hello, Slate!"))
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SEditableTextBox)
.Text(FText::FromString("Enter text..."))
.OnTextChanged(this, &SMyWidget::OnTextChanged)
.OnTextCommitted(this, &SMyWidget::OnTextCommitted)
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(SEditableTextBox)
.Text(FText::FromString("Styled TextBox"))
.Font(FSlateFontInfo("Arial", 16))
.ForegroundColor(FSlateColor(FLinearColor::White))
.BackgroundColor(FSlateColor(FLinearColor::Black))
.OnTextChanged(this, &SMyWidget::OnTextChanged)
.OnTextCommitted(this, &SMyWidget::OnTextCommitted)
]
];
}
private:
void OnTextChanged(const FText& NewText)
{
// 文本变化后的处理逻辑
UE_LOG(LogTemp, Warning, TEXT("Text changed: %s"), *NewText.ToString());
}
void OnTextCommitted(const FText& NewText, ETextCommit::Type CommitType)
{
// 文本提交后的处理逻辑
UE_LOG(LogTemp, Warning, TEXT("Text committed: %s"), *NewText.ToString());
}
};
1.7.3 总结
SEditableTextBox
是一个用于创建可编辑文本框的控件,通过设置其属性,可以自定义文本框的外观和行为。SEditableTextBox
支持文本变化和提交事件处理,可以绑定函数来响应用户输入。通过了解和使用 SEditableTextBox
,可以在Slate UI中实现各种用户输入功能,提供良好的用户体验。
1.8 SOverlay
1.8.1 SOverlay的作用
SOverlay
是Unreal Engine Slate框架中的一个重要布局控件,用于创建叠加布局。它允许多个子控件彼此叠加,从而实现复杂的UI布局,比如背景图像上叠加文本或按钮。SOverlay
是一个容器控件,可以包含多个子控件,并根据添加顺序将它们叠加显示。
- 叠加布局:允许多个子控件在同一位置叠加显示,常用于背景和前景元素的组合。
- 层次管理:可以管理多个子控件的层次,使得控件按照添加顺序依次显示。
- 灵活布局:适用于需要将多个元素叠加在一起的UI布局场景。
1.8.2 使用方法
创建一个 SOverlay
控件,并添加多个子控件,这些子控件将按顺序叠加显示。
cpp
SNew(SOverlay)
+ SOverlay::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Background Text"))
]
+ SOverlay::Slot()
[
SNew(SButton)
.Text(FText::FromString("Foreground Button"))
]
可以通过设置 Slot
的属性来控制每个子控件的位置和大小。
cpp
SNew(SOverlay)
+ SOverlay::Slot()
[
SNew(SImage)
.Image(FCoreStyle::Get().GetBrush("Checkerboard"))
]
+ SOverlay::Slot()
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString("Centered Text"))
]
+ SOverlay::Slot()
[
SNew(SButton)
.Text(FText::FromString("Button"))
.HAlign(HAlign_Right)
.VAlign(VAlign_Bottom)
]
以下是一个完整的示例,展示了如何在Slate应用中使用 SOverlay
控件,并叠加多个子控件。
cpp
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Images/SImage.h"
#include "Widgets/Input/SButton.h"
#include "Widgets/Layout/SOverlay.h"
#include "Widgets/Layout/SBox.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
#include "Brushes/SlateColorBrush.h"
#include "Styling/CoreStyle.h"
class SMyOverlayWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyOverlayWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SOverlay)
+ SOverlay::Slot()
[
SNew(SImage)
.Image(FCoreStyle::Get().GetBrush("Checkerboard"))
]
+ SOverlay::Slot()
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString("Centered Text"))
]
+ SOverlay::Slot()
[
SNew(SButton)
.HAlign(HAlign_Right)
.VAlign(VAlign_Bottom)
.Text(FText::FromString("Button"))
]
];
}
};
每个 SOverlay::Slot
都代表一个子控件的插槽,可以通过链式调用设置对齐方式和填充等属性。
cpp
+ SOverlay::Slot()
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(FText::FromString("Centered Text"))
]
控件叠加顺序:子控件的叠加顺序由添加到 SOverlay
的顺序决定,越后添加的子控件在叠加层次上越靠前。
1.8.3 总结
SOverlay
是一个非常有用的布局控件,用于创建叠加布局。通过使用 SOverlay
,可以方便地在同一位置叠加多个子控件,实现复杂的UI布局需求。理解和使用 SOverlay
可以帮助你在Slate UI中创建更灵活和美观的用户界面。
1.9 SHorizontalBox、SVerticalBox
1.9.1 SHorizontalBox 和 SVerticalBox 的作用
SHorizontalBox
和 SVerticalBox
是Unreal Engine Slate框架中的布局控件,用于创建水平和垂直布局。它们允许将多个子控件水平或垂直排列,并提供了灵活的排列和对齐方式。
- 布局管理:用于管理和排列多个子控件,使它们在水平或垂直方向上依次排列。
- 对齐和填充:支持对每个子控件进行对齐和填充设置,提供灵活的布局选项。
- 容器控件:可以包含多个子控件,是构建复杂UI布局的基础。
1.9.2 使用方法
SHorizontalBox
用于将子控件水平排列。
cpp
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Left"))
]
+ SHorizontalBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Center"))
]
+ SHorizontalBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Right"))
]
可以通过设置 Slot
的属性来控制每个子控件的对齐方式和填充。
cpp
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(STextBlock)
.Text(FText::FromString("Auto Width"))
]
+ SHorizontalBox::Slot()
.FillWidth(1)
[
SNew(STextBlock)
.Text(FText::FromString("Fill Width"))
]
+ SHorizontalBox::Slot()
.HAlign(HAlign_Right)
[
SNew(STextBlock)
.Text(FText::FromString("Right Aligned"))
]
SVerticalBox
用于将子控件垂直排列。
cpp
SNew(SVerticalBox)
+ SVerticalBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Top"))
]
+ SVerticalBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Middle"))
]
+ SVerticalBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Bottom"))
]
可以通过设置 Slot
的属性来控制每个子控件的对齐方式和填充。
cpp
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Auto Height"))
]
+ SVerticalBox::Slot()
.FillHeight(1)
[
SNew(STextBlock)
.Text(FText::FromString("Fill Height"))
]
+ SVerticalBox::Slot()
.VAlign(VAlign_Bottom)
[
SNew(STextBlock)
.Text(FText::FromString("Bottom Aligned"))
]
以下是一个完整的示例,展示了如何在Slate应用中使用 SHorizontalBox
和 SVerticalBox
控件,并设置子控件的对齐方式和填充属性。
cpp
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Layout/SHorizontalBox.h"
#include "Widgets/Layout/SVerticalBox.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
class SMyLayoutWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyLayoutWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Top Text"))
]
+ SVerticalBox::Slot()
.FillHeight(1)
[
SNew(SHorizontalBox)
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(STextBlock)
.Text(FText::FromString("Left Text"))
]
+ SHorizontalBox::Slot()
.FillWidth(1)
[
SNew(STextBlock)
.Text(FText::FromString("Center Text"))
]
+ SHorizontalBox::Slot()
.AutoWidth()
[
SNew(STextBlock)
.Text(FText::FromString("Right Text"))
]
]
+ SVerticalBox::Slot()
.AutoHeight()
[
SNew(STextBlock)
.Text(FText::FromString("Bottom Text"))
]
];
}
};
1.9.3 总结
SHorizontalBox
和 SVerticalBox
是用于创建水平和垂直布局的控件,通过设置其 Slot
属性,可以灵活地排列和对齐子控件。这两个控件是构建复杂UI布局的重要工具,通过了解和使用它们,可以创建结构化和美观的用户界面。
1.10 SScrollBox
1.10.1 SScrollBox的作用
SScrollBox
是Unreal Engine Slate框架中的一个重要控件,用于创建带有滚动条的可滚动区域。它允许你在有限的空间内显示大量内容,并通过滚动条进行浏览。SScrollBox
支持水平和垂直滚动,可以包含多个子控件,并提供各种滚动选项和事件处理。
- 可滚动内容区域:在有限空间内显示大量内容,并通过滚动条进行浏览。
- 水平和垂直滚动:支持内容的水平和垂直滚动。
- 事件处理:提供滚动事件处理,允许开发者在滚动时执行特定操作。
1.10.2 使用方法
创建一个 SScrollBox
控件,并添加多个子控件,这些子控件可以通过滚动条进行浏览。
cpp
SNew(SScrollBox)
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 1"))
]
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 2"))
]
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 3"))
]
可以通过设置 Orientation
属性来控制滚动方向(水平或垂直)。
cpp
SNew(SScrollBox)
.Orientation(Orient_Horizontal)
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 1"))
]
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 2"))
]
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 3"))
]
可以绑定 OnUserScrolled
事件处理程序,以处理滚动事件。
cpp
void OnUserScrolled(float ScrollOffset)
{
UE_LOG(LogTemp, Warning, TEXT("Scrolled to offset: %f"), ScrollOffset);
}
SNew(SScrollBox)
.OnUserScrolled(this, &SMyWidget::OnUserScrolled)
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Scrollable Item"))
]
以下是一个完整的示例,展示了如何在Slate应用中使用 SScrollBox
控件,并处理滚动事件。
cpp
#include "Widgets/Text/STextBlock.h"
#include "Widgets/Layout/SScrollBox.h"
#include "Widgets/SCompoundWidget.h"
#include "Widgets/DeclarativeSyntaxSupport.h"
class SMyScrollableWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyScrollableWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SScrollBox)
.OnUserScrolled(this, &SMyScrollableWidget::OnUserScrolled)
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 1"))
]
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 2"))
]
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 3"))
]
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 4"))
]
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 5"))
]
];
}
private:
void OnUserScrolled(float ScrollOffset)
{
// 处理滚动事件
UE_LOG(LogTemp, Warning, TEXT("Scrolled to offset: %f"), ScrollOffset);
}
};
每个 SScrollBox::Slot
都代表一个子控件的插槽,可以通过链式调用设置对齐方式和填充等属性。
cpp
+ SScrollBox::Slot()
[
SNew(STextBlock)
.Text(FText::FromString("Item 1"))
]
使用 Orientation
属性设置滚动方向,默认为垂直方向(Orient_Vertical
)。
cpp
SNew(SScrollBox)
.Orientation(Orient_Horizontal)
使用 OnUserScrolled
属性绑定滚动事件处理程序,当用户滚动时,会调用指定的处理函数。
cpp
.OnUserScrolled(this, &SMyScrollableWidget::OnUserScrolled)
1.10.3 总结
SScrollBox
是一个非常有用的控件,用于创建带有滚动条的可滚动内容区域。通过使用 SScrollBox
,可以在有限的空间内显示大量内容,并通过滚动条进行浏览。了解和使用 SScrollBox
,可以帮助你在Slate UI中创建更灵活和用户友好的界面。
2 类之间的关系
Unreal Engine Slate框架中的这些类有着明确的继承关系和职责划分,构成了一个强大的UI组件系统。下面是对这些类之间关系的简要说明。
2.1 主要类的继承关系和职责
-
SWidget
- 职责 :
SWidget
是所有Slate控件的基类,定义了所有控件的基本接口和行为,如渲染、事件处理和布局管理。 - 关系 :
SWidget
是其他所有控件(包括复合控件和叶子控件)的基类。
- 职责 :
-
SCompoundWidget
- 职责 :
SCompoundWidget
是一种复合控件,可以包含其他子控件。它简化了控件的构造和管理过程。 - 关系 :继承自
SWidget
,是许多自定义控件(如SMyWidget
)的基类。
- 职责 :
-
SLeafWidget
- 职责 :
SLeafWidget
是一种叶子控件,不包含子控件。它通常用于实现独立的UI元素,如文本块(STextBlock
)。 - 关系 :继承自
SWidget
,用于创建简单的UI元素。
- 职责 :
-
SPanel
- 职责 :
SPanel
是一种布局控件,可以包含多个子控件并管理它们的布局和排列。 - 关系 :继承自
SWidget
,是其他布局控件(如SVerticalBox
、SHorizontalBox
)的基类。
- 职责 :
-
SOverlay
- 职责 :
SOverlay
用于创建叠加布局,允许多个子控件彼此叠加。 - 关系 :继承自
SPanel
,用于实现叠加布局。
- 职责 :
-
SHorizontalBox
- 职责 :
SHorizontalBox
用于将子控件水平排列。 - 关系 :继承自
SPanel
,用于实现水平布局。
- 职责 :
-
SVerticalBox
- 职责 :
SVerticalBox
用于将子控件垂直排列。 - 关系 :继承自
SPanel
,用于实现垂直布局。
- 职责 :
-
SScrollBox
- 职责 :
SScrollBox
用于创建带有滚动条的可滚动区域,支持内容的水平和垂直滚动。 - 关系 :继承自
SPanel
,用于实现可滚动内容区域。
- 职责 :
-
STextBlock
- 职责 :
STextBlock
用于显示文本,是一个典型的叶子控件。 - 关系 :继承自
SLeafWidget
,用于显示静态文本。
- 职责 :
-
SButton
- 职责 :
SButton
用于创建按钮,支持用户交互和点击事件。 - 关系 :继承自
SCompoundWidget
,用于实现交互式按钮。
- 职责 :
2.2 类之间的关系图
SWidget
├── SLeafWidget
│ ├── STextBlock
│ └── 其他叶子控件
├── SCompoundWidget
│ ├── SButton
│ └── 自定义复合控件(如 SMyWidget)
├── SPanel
│ ├── SOverlay
│ ├── SHorizontalBox
│ ├── SVerticalBox
│ ├── SScrollBox
│ └── 自定义布局控件
2.3 具体示例和解释
-
SWidget
SWidget
是所有控件的基类,提供基本的接口和行为,如渲染、事件处理等。 -
SCompoundWidget
SCompoundWidget
继承自SWidget
,用于创建包含子控件的复合控件。你可以在Construct
方法中使用声明式语法添加子控件。
cpp
class SMyCompoundWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyCompoundWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(SVerticalBox)
+ SVerticalBox::Slot()
[
SNew(STextBlock).Text(FText::FromString("Hello, Slate!"))
]
+ SVerticalBox::Slot()
[
SNew(SButton).Text(FText::FromString("Click Me"))
]
];
}
};
- SLeafWidget
SLeafWidget
继承自SWidget
,用于创建不包含子控件的独立UI元素。
cpp
class SMyLeafWidget : public SLeafWidget
{
public:
SLATE_BEGIN_ARGS(SMyLeafWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
// 无子控件,通常用于独立元素
}
};
- SPanel
SPanel
继承自SWidget
,用于管理和排列多个子控件。具体布局控件(如SHorizontalBox
,SVerticalBox
)继承自SPanel
。
cpp
class SMyPanel : public SPanel
{
public:
SLATE_BEGIN_ARGS(SMyPanel) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
// 子控件的排列逻辑
}
};
2.4 总结
这些类通过继承关系形成了一个强大的UI组件系统,允许开发者创建复杂且功能丰富的用户界面。了解这些类之间的关系和职责,可以帮助你更好地使用Slate框架来开发Unreal Engine中的用户界面。
3 Slate和UMG
Unreal Engine 提供了两种主要的用户界面开发工具:Slate 和 Unreal Motion Graphics (UMG)。这两者在许多方面是相互关联的,Slate 是底层框架,而 UMG 是一种高级的、更加用户友好的UI构建工具。以下是 Slate 和 UMG 之间的联系和差异,以及如何在开发中结合使用这两者的概述。
3.1 Slate 和 UMG 的联系
-
底层与高级接口:
- Slate:是 Unreale Engine 的底层 UI 框架。它是使用 C++ 编写的,用于创建高度定制化和性能优化的用户界面。所有的 UMG 控件最终都是基于 Slate 实现的。
- UMG:是基于 Slate 的高级 UI 编辑工具。它提供了一个直观的拖放界面,让开发者可以在 Editor 中创建和设计 UI,而不需要编写大量的 C++ 代码。
-
组件关系:
- Slate 控件:UMG 中的每一个 Widget(控件)在底层都是通过 Slate 实现的。UMG 控件通常是 Slate 控件的包装器,提供了一个易于使用的接口和绑定功能。
- SWidget 和 UWidget :
SWidget
是 Slate 控件的基类,而UWidget
是 UMG 控件的基类。UMG 控件通过将SWidget
嵌入到UWidget
中,使得在 Editor 中的设计和运行时的渲染可以无缝衔接。
-
混合使用:
- 开发者可以在 UMG 蓝图中使用自定义的 Slate 控件。这通过实现一个
UWidget
的子类来实现,该子类在其RebuildWidget
方法中返回自定义的 Slate 控件。 - 可以在 Slate 中嵌入 UMG 控件,允许复杂的 UI 布局和高级交互。
- 开发者可以在 UMG 蓝图中使用自定义的 Slate 控件。这通过实现一个
3.2 Slate 和 UMG 的差异
-
开发方式:
- Slate:需要编写 C++ 代码,提供了高度的灵活性和控制。适用于需要高度自定义和优化的 UI。
- UMG:可以通过蓝图或 C++ 代码创建 UI。更适合快速原型开发和设计人员使用。
-
设计方式:
- Slate:使用声明式语法在 C++ 中定义 UI 元素,布局和样式。
- UMG:使用直观的拖放界面在 Editor 中设计 UI,提供了 WYSIWYG(所见即所得)的设计体验。
-
性能:
- Slate:通常性能更好,因为它是纯 C++ 实现的,提供了更直接的控制。
- UMG:由于其更高级的抽象层,可能会有一些性能开销,但在大多数应用中是足够的。
3.3 结合使用 Slate 和 UMG
示例:在 UMG 中使用自定义 Slate 控件
首先,定义一个自定义的 Slate 控件:
cpp
#pragma once
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
class SMyCustomSlateWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMyCustomSlateWidget) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
ChildSlot
[
SNew(STextBlock).Text(FText::FromString("Hello from Slate!"))
];
}
};
然后,创建一个包装器,将这个 Slate 控件嵌入到 UMG 中:
cpp
#pragma once
#include "CoreMinimal.h"
#include "Components/Widget.h"
#include "MyCustomWidget.generated.h"
UCLASS()
class UMyCustomWidget : public UWidget
{
GENERATED_BODY()
public:
virtual TSharedRef<SWidget> RebuildWidget() override
{
return SNew(SMyCustomSlateWidget);
}
};
最后,在 Editor 中,将这个自定义 UMG 控件添加到你的 UMG 蓝图中。
示例:在 Slate 中嵌入 UMG 控件
你也可以在 Slate 中嵌入 UMG 控件:
cpp
#include "SlateBasics.h"
#include "SlateExtras.h"
#include "Widgets/SCompoundWidget.h"
#include "Blueprint/UserWidget.h"
#include "UObject/ConstructorHelpers.h"
class SMySlateWidgetWithUMG : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SMySlateWidgetWithUMG) {}
SLATE_END_ARGS()
void Construct(const FArguments& InArgs)
{
UUserWidget* UserWidget = CreateWidget<UUserWidget>(GWorld, LoadClass<UUserWidget>(nullptr, TEXT("/Game/PathToYourUMGWidget.YourUMGWidget_C")));
ChildSlot
[
SNew(SOverlay)
+ SOverlay::Slot()
[
UserWidget->TakeWidget()
]
];
}
};
3.4 总结
Slate 和 UMG 是 Unreale Engine 中的两个主要 UI 工具,前者是底层的 UI 框架,后者是基于前者的高级工具。Slate 提供了高度灵活性和性能优化,适合需要自定义 UI 组件的开发,而 UMG 提供了更直观和易用的设计界面,适合快速开发和设计人员使用。通过结合使用这两者,可以创建功能丰富且性能优越的用户界面。