【UE Slate】 虚幻引擎Slate开发快速入门

目录

  • [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 总结)
  • 🙋‍♂️ 作者:海码007
  • 📜 专栏:UE虚幻引擎专栏
  • 💥 标题:【UE Slate】 虚幻引擎Slate开发快速入门
  • ❣️ 寄语:书到用时方恨少,事非经过不知难!
  • 🎈 最后:文章作者技术和水平有限,如果文中出现错误,希望大家能指正,同时有问题的话,欢迎大家留言讨论。

0 引言

项目需要对UE引擎进行二次开发,具体来说是编辑器开发。而Slate知识是进行编辑器开发的基础,这个就是UE中UMG界面开发的C++版本,只不过是通过写代码的方式来进行页面的布局。

1 Slate框架

1.0 控件布局

在Unreal Engine的Slate框架中,Construct方法是用来初始化控件的。ChildSlot是一个特殊的插槽,用于指定复合控件(如SCompoundWidget)的子控件。下面我会详细解释ChildSlot的作用和使用方法。

ChildSlot的作用

ChildSlot是复合控件(例如SCompoundWidget)中的一个插槽,用于容纳单个子控件。通过定义ChildSlot,你可以将其他Slate控件嵌入到你的自定义控件中。

ChildSlot的使用方法

  1. 基本用法

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!"。

  1. 布局和对齐

你可以通过链式调用来设置子控件的布局和对齐方式。例如,可以使用HAlignVAlign属性来设置水平和垂直对齐方式。

cpp 复制代码
void Construct(const FArguments& InArgs)
{
    ChildSlot
    .HAlign(HAlign_Center)  // 水平居中对齐
    .VAlign(VAlign_Center)  // 垂直居中对齐
    [
        SNew(STextBlock)
        .Text(FText::FromString("Centered Text"))
    ];
}
  1. 复杂布局

你可以在ChildSlot中嵌套其他复合控件(例如SVerticalBoxSHorizontalBox)来创建更复杂的布局。

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();
    }
};

总结

ChildSlotSCompoundWidget中的一个插槽,用于定义控件的内容和布局。通过在Construct方法中使用ChildSlot,你可以将其他Slate控件嵌入到你的自定义控件中,并通过链式调用设置对齐和填充属性。了解如何使用ChildSlot可以帮助你创建复杂且功能丰富的用户界面。

1.1 SWidget

SWidget 是Unreal Engine中Slate框架的基类,所有的UI控件都直接或间接地继承自 SWidgetSWidget 提供了Slate控件的基本属性和行为,如渲染、事件处理和布局。

1.1.1 SWidget的主要作用

  1. 基类作用SWidget 是所有Slate控件的基类,定义了控件的基本接口和行为。
  2. 渲染:管理控件的绘制过程。
  3. 事件处理:处理用户输入事件,如鼠标点击、键盘输入等。
  4. 布局管理:管理控件的布局和排列。
  5. 属性系统:支持Slate的属性绑定和更新机制。
  6. 状态管理:管理控件的状态,如可见性、启用状态等。

1.1.2 SWidget的关键方法

  1. 渲染相关方法:
  • OnPaint:绘制控件内容的核心方法。
cpp 复制代码
virtual int32 OnPaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, 
                      FSlateWindowElementList& OutDrawElements, int32 LayerId, 
                      const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const;
  1. 布局相关方法
  • ComputeDesiredSize:计算控件的理想大小。
cpp 复制代码
virtual FVector2D ComputeDesiredSize(float LayoutScaleMultiplier) const;
  • ArrangeChildren:安排子控件的位置和大小。
cpp 复制代码
virtual void ArrangeChildren(const FGeometry& AllottedGeometry, FArrangedChildren& ArrangedChildren) const;
  1. 事件处理相关方法
  • OnMouseButtonDown:处理鼠标按下事件。

    cpp 复制代码
    virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent);
  • OnMouseButtonUp:处理鼠标松开事件。

    cpp 复制代码
    virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent);
  • OnMouseMove:处理鼠标移动事件。

    cpp 复制代码
    virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent);

1.1.3 使用SWidget创建自定义控件

  1. 创建自定义控件类:继承自 SCompoundWidgetSLeafWidget,具体取决于你的控件是否包含子控件。SCompoundWidget 继承自 SWidget 并添加了一些额外的功能,如支持包含子控件。

  2. 实现控件的构造函数和关键方法:以下是一个创建自定义控件的完整示例:

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();
    }
};

解释构造函数和方法

  1. 构造函数:Construct 方法用于初始化控件。SLATE_BEGIN_ARGSSLATE_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)
        ]
    ];
}
  1. 事件处理函数: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的主要作用

  1. 容器控件SCompoundWidget 主要用作容器控件,可以包含一个或多个子控件。
  2. 简化构造 :提供了简化的构造方法 Construct,允许使用Declarative Syntax(声明式语法)来定义子控件和布局。
  3. 复合行为:允许自定义复合控件的行为,如响应用户输入和控制子控件的排列方式。

关键方法和成员

  1. 构造方法
    SCompoundWidget 使用 Construct 方法来初始化控件。这与 SWidget 不同,SWidget 需要手动实现一些初始化逻辑。
cpp 复制代码
void Construct(const FArguments& InArgs);
  1. 子控件的布局
    通过 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_ARGSSLATE_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. 布局管理:管理和排列其子控件的位置和大小。
  2. 容器控件:可以包含多个子控件,提供容器功能。
  3. 扩展性:允许开发者继承并实现自定义的布局逻辑。

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. 显示文本:用于在用户界面中显示静态或动态文本。
  2. 文本样式:支持丰富的文本样式和格式设置选项。
  3. 绑定和更新:可以绑定到数据源,并动态更新显示的文本内容。

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. 用户交互:提供一个交互点,用户可以通过点击按钮来触发特定的操作或事件。
  2. 可定制外观:可以设置按钮的外观样式,如按钮的文本、图片、颜色等。
  3. 事件处理:支持点击事件和其他交互事件,允许开发者定义按钮点击后的行为。

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. 用户输入:允许用户在文本框中输入和编辑文本。
  2. 数据绑定:可以绑定到数据源,并动态更新显示的文本内容。
  3. 样式定制:支持多种样式设置,如字体、颜色、对齐方式等。
  4. 事件处理:提供输入事件和其他交互事件,允许开发者定义文本变化后的行为。

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))

使用 OnTextChangedOnTextCommitted 属性绑定事件处理程序,以处理文本变化和提交事件。

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 是一个容器控件,可以包含多个子控件,并根据添加顺序将它们叠加显示。

  1. 叠加布局:允许多个子控件在同一位置叠加显示,常用于背景和前景元素的组合。
  2. 层次管理:可以管理多个子控件的层次,使得控件按照添加顺序依次显示。
  3. 灵活布局:适用于需要将多个元素叠加在一起的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 的作用

SHorizontalBoxSVerticalBox 是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应用中使用 SHorizontalBoxSVerticalBox 控件,并设置子控件的对齐方式和填充属性。

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 总结

SHorizontalBoxSVerticalBox 是用于创建水平和垂直布局的控件,通过设置其 Slot 属性,可以灵活地排列和对齐子控件。这两个控件是构建复杂UI布局的重要工具,通过了解和使用它们,可以创建结构化和美观的用户界面。

1.10 SScrollBox

1.10.1 SScrollBox的作用

SScrollBox 是Unreal Engine Slate框架中的一个重要控件,用于创建带有滚动条的可滚动区域。它允许你在有限的空间内显示大量内容,并通过滚动条进行浏览。SScrollBox 支持水平和垂直滚动,可以包含多个子控件,并提供各种滚动选项和事件处理。

  1. 可滚动内容区域:在有限空间内显示大量内容,并通过滚动条进行浏览。
  2. 水平和垂直滚动:支持内容的水平和垂直滚动。
  3. 事件处理:提供滚动事件处理,允许开发者在滚动时执行特定操作。

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 主要类的继承关系和职责

  1. SWidget

    • 职责SWidget 是所有Slate控件的基类,定义了所有控件的基本接口和行为,如渲染、事件处理和布局管理。
    • 关系SWidget 是其他所有控件(包括复合控件和叶子控件)的基类。
  2. SCompoundWidget

    • 职责SCompoundWidget 是一种复合控件,可以包含其他子控件。它简化了控件的构造和管理过程。
    • 关系 :继承自 SWidget,是许多自定义控件(如 SMyWidget)的基类。
  3. SLeafWidget

    • 职责SLeafWidget 是一种叶子控件,不包含子控件。它通常用于实现独立的UI元素,如文本块(STextBlock)。
    • 关系 :继承自 SWidget,用于创建简单的UI元素。
  4. SPanel

    • 职责SPanel 是一种布局控件,可以包含多个子控件并管理它们的布局和排列。
    • 关系 :继承自 SWidget,是其他布局控件(如 SVerticalBoxSHorizontalBox)的基类。
  5. SOverlay

    • 职责SOverlay 用于创建叠加布局,允许多个子控件彼此叠加。
    • 关系 :继承自 SPanel,用于实现叠加布局。
  6. SHorizontalBox

    • 职责SHorizontalBox 用于将子控件水平排列。
    • 关系 :继承自 SPanel,用于实现水平布局。
  7. SVerticalBox

    • 职责SVerticalBox 用于将子控件垂直排列。
    • 关系 :继承自 SPanel,用于实现垂直布局。
  8. SScrollBox

    • 职责SScrollBox 用于创建带有滚动条的可滚动区域,支持内容的水平和垂直滚动。
    • 关系 :继承自 SPanel,用于实现可滚动内容区域。
  9. STextBlock

    • 职责STextBlock 用于显示文本,是一个典型的叶子控件。
    • 关系 :继承自 SLeafWidget,用于显示静态文本。
  10. SButton

    • 职责SButton 用于创建按钮,支持用户交互和点击事件。
    • 关系 :继承自 SCompoundWidget,用于实现交互式按钮。

2.2 类之间的关系图

复制代码
SWidget
├── SLeafWidget
│   ├── STextBlock
│   └── 其他叶子控件
├── SCompoundWidget
│   ├── SButton
│   └── 自定义复合控件(如 SMyWidget)
├── SPanel
│   ├── SOverlay
│   ├── SHorizontalBox
│   ├── SVerticalBox
│   ├── SScrollBox
│   └── 自定义布局控件

2.3 具体示例和解释

  1. SWidget
    SWidget 是所有控件的基类,提供基本的接口和行为,如渲染、事件处理等。

  2. 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"))
            ]
        ];
    }
};
  1. SLeafWidget
    SLeafWidget 继承自 SWidget,用于创建不包含子控件的独立UI元素。
cpp 复制代码
class SMyLeafWidget : public SLeafWidget
{
public:
    SLATE_BEGIN_ARGS(SMyLeafWidget) {}
    SLATE_END_ARGS()

    void Construct(const FArguments& InArgs)
    {
        // 无子控件,通常用于独立元素
    }
};
  1. 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 提供了两种主要的用户界面开发工具:SlateUnreal Motion Graphics (UMG)。这两者在许多方面是相互关联的,Slate 是底层框架,而 UMG 是一种高级的、更加用户友好的UI构建工具。以下是 Slate 和 UMG 之间的联系和差异,以及如何在开发中结合使用这两者的概述。

3.1 Slate 和 UMG 的联系

  1. 底层与高级接口

    • Slate:是 Unreale Engine 的底层 UI 框架。它是使用 C++ 编写的,用于创建高度定制化和性能优化的用户界面。所有的 UMG 控件最终都是基于 Slate 实现的。
    • UMG:是基于 Slate 的高级 UI 编辑工具。它提供了一个直观的拖放界面,让开发者可以在 Editor 中创建和设计 UI,而不需要编写大量的 C++ 代码。
  2. 组件关系

    • Slate 控件:UMG 中的每一个 Widget(控件)在底层都是通过 Slate 实现的。UMG 控件通常是 Slate 控件的包装器,提供了一个易于使用的接口和绑定功能。
    • SWidget 和 UWidgetSWidget 是 Slate 控件的基类,而 UWidget 是 UMG 控件的基类。UMG 控件通过将 SWidget 嵌入到 UWidget 中,使得在 Editor 中的设计和运行时的渲染可以无缝衔接。
  3. 混合使用

    • 开发者可以在 UMG 蓝图中使用自定义的 Slate 控件。这通过实现一个 UWidget 的子类来实现,该子类在其 RebuildWidget 方法中返回自定义的 Slate 控件。
    • 可以在 Slate 中嵌入 UMG 控件,允许复杂的 UI 布局和高级交互。

3.2 Slate 和 UMG 的差异

  1. 开发方式

    • Slate:需要编写 C++ 代码,提供了高度的灵活性和控制。适用于需要高度自定义和优化的 UI。
    • UMG:可以通过蓝图或 C++ 代码创建 UI。更适合快速原型开发和设计人员使用。
  2. 设计方式

    • Slate:使用声明式语法在 C++ 中定义 UI 元素,布局和样式。
    • UMG:使用直观的拖放界面在 Editor 中设计 UI,提供了 WYSIWYG(所见即所得)的设计体验。
  3. 性能

    • 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 提供了更直观和易用的设计界面,适合快速开发和设计人员使用。通过结合使用这两者,可以创建功能丰富且性能优越的用户界面。

相关推荐
Doc.S4 小时前
多无人机任务自定义(基于ZJU-FAST-Lab / EGO-Planner-v2)
游戏引擎·无人机·cocos2d
nnsix6 小时前
Unity OpenXR开发HTC Vive Cosmos
unity·游戏引擎
nnsix7 小时前
Unity OpenXR,扳机键交互UI时,必须按下扳机才触发
unity·游戏引擎
老朱佩琪!7 小时前
Unity访问者模式
unity·游戏引擎·访问者模式
不定时总结的那啥8 小时前
Unity实现点击Console消息自动选中预制体的方法
unity·游戏引擎
nnsix8 小时前
Unity OpenXR 关闭手柄的震动
unity·游戏引擎
CreasyChan8 小时前
Unity 中的反射使用详解
unity·c#·游戏引擎·游戏开发
天途小编9 小时前
无人机操控模式解析:美国手、日本手、中国手
游戏引擎·无人机·cocos2d
90后小陈老师21 小时前
Unity教学 项目2 2D闯关游戏
游戏·unity·游戏引擎
噗噗夹的TA之旅1 天前
Unity Shader 学习20:URP LitForwardPass PBR 解析
学习·unity·游戏引擎·图形渲染·技术美术