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

news2024/9/20 5:39:19

目录

  • 0 引言
  • 1 Slate框架
    • 1.0 控件布局
    • 1.1 SWidget
      • 1.1.1 SWidget的主要作用
      • 1.1.2 SWidget的关键方法
      • 1.1.3 使用SWidget创建自定义控件
      • 1.1.4 结论
    • 1.2 SCompoundWidget
      • 1.2.1 SCompoundWidget的主要作用
      • 1.2.2 SCompoundWidget的使用示例
      • 1.2.3 SCompoundWidget的关系
      • 1.2.4 总结
    • 1.3 SLeafWidget
    • 1.4 SPanel
      • 1.4.1 SPanel的作用
      • 1.4.2 使用方法
      • 1.4.3 总结
    • 1.5 STextBlock
      • 1.5.1 STextBlock的作用
      • 1.5.2 使用方法
      • 1.5.3 总结
    • 1.6 SButton
      • 1.6.1 SButton的作用
      • 1.6.2 使用方法
      • 1.6.3 总结
    • 1.7 SEditableTextBox
      • 1.7.1 SEditableTextBox的作用
      • 1.7.2 使用方法
      • 1.7.3 总结
    • 1.8 SOverlay
      • 1.8.1 SOverlay的作用
      • 1.8.2 使用方法
      • 1.8.3 总结
    • 1.9 SHorizontalBox、SVerticalBox
      • 1.9.1 SHorizontalBox 和 SVerticalBox 的作用
      • 1.9.2 使用方法
      • 1.9.3 总结
    • 1.10 SScrollBox
      • 1.10.1 SScrollBox的作用
      • 1.10.2 使用方法
      • 1.10.3 总结
  • 2 类之间的关系
    • 2.1 主要类的继承关系和职责
    • 2.2 类之间的关系图
    • 2.3 具体示例和解释
    • 2.4 总结
  • 3 Slate和UMG
    • 3.1 Slate 和 UMG 的联系
    • 3.2 Slate 和 UMG 的差异
    • 3.3 结合使用 Slate 和 UMG
    • 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来定义一个文本块控件。

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属性来设置水平和垂直对齐方式。

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

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

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在自定义控件中定义复杂的布局。

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

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

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

    virtual FReply OnMouseMove(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent);
    

1.1.3 使用SWidget创建自定义控件

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

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

#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 宏定义控件的构造参数。
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() 表示事件已处理。
FReply OnButtonClick()
{
    UE_LOG(LogTemp, Warning, TEXT("Button clicked!"));
    return FReply::Handled();
}

自定义控件的使用

将自定义控件添加到UI中,可以通过在父控件或Slate应用程序中创建实例。

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 需要手动实现一些初始化逻辑。
void Construct(const FArguments& InArgs);
  1. 子控件的布局
    通过 ChildSlot 成员,可以使用声明式语法来定义复合控件的子控件和布局。
TSlotBase<SlotType>& ChildSlot;

1.2.2 SCompoundWidget的使用示例

定义一个自定义控件

头文件(.h):

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

#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 结束定义。参数可以包括控件的属性和事件处理程序。

SLATE_BEGIN_ARGS(SMyCompoundWidget) {}
SLATE_END_ARGS()

Construct 方法用于初始化控件的内容和布局。通过 ChildSlot 成员,使用声明式语法定义子控件。

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 方法。

FReply OnButtonClick()
{
    UE_LOG(LogTemp, Warning, TEXT("Button clicked!"));
    return FReply::Handled();
}

在项目中使用自定义控件:要在项目中使用这个自定义控件,可以在Slate应用程序或其他Slate控件中实例化 SMyCompoundWidget

// 假设这是某个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)

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

#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中使用自定义面板,可以通过声明式语法来添加子控件。

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 控件,并设置要显示的文本。

SNew(STextBlock)
.Text(FText::FromString("Hello, Slate!"))

可以使用各种属性来设置文本的样式,如字体、颜色和对齐方式。

SNew(STextBlock)
.Text(FText::FromString("Styled Text"))
.Font(FSlateFontInfo("Arial", 24))
.ColorAndOpacity(FSlateColor(FLinearColor::Red))
.Justification(ETextJustify::Center)

可以绑定一个动态属性,当属性值变化时,文本会自动更新。

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 控件。

#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 使用方法

创建一个简单的按钮,并设置按钮上的文本。

SNew(SButton)
.Text(FText::FromString("Click Me"))
.OnClicked(this, &SMyWidget::OnButtonClick)

可以通过各种属性来自定义按钮的样式,例如按钮的文本、字体、颜色等。

SNew(SButton)
.Text(FText::FromString("Styled Button"))
.ButtonColorAndOpacity(FLinearColor::Blue)
.ContentPadding(FMargin(10))

使用 OnClicked 属性绑定一个处理函数,该函数将在按钮被点击时调用。

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 控件,并处理按钮点击事件。

#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 使用方法

创建一个简单的可编辑文本框,并设置初始文本。

SNew(SEditableTextBox)
.Text(FText::FromString("Initial Text"))

可以通过各种属性来自定义文本框的样式,例如字体、颜色、对齐方式等。

SNew(SEditableTextBox)
.Text(FText::FromString("Styled TextBox"))
.Font(FSlateFontInfo("Arial", 16))
.ForegroundColor(FSlateColor(FLinearColor::White))
.BackgroundColor(FSlateColor(FLinearColor::Black))

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

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 控件,并处理文本变化和提交事件。

#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 控件,并添加多个子控件,这些子控件将按顺序叠加显示。

SNew(SOverlay)
+ SOverlay::Slot()
[
    SNew(STextBlock)
    .Text(FText::FromString("Background Text"))
]
+ SOverlay::Slot()
[
    SNew(SButton)
    .Text(FText::FromString("Foreground Button"))
]

可以通过设置 Slot 的属性来控制每个子控件的位置和大小。

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 控件,并叠加多个子控件。

#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 都代表一个子控件的插槽,可以通过链式调用设置对齐方式和填充等属性。

+ 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 用于将子控件水平排列。

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 的属性来控制每个子控件的对齐方式和填充。

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 用于将子控件垂直排列。

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 的属性来控制每个子控件的对齐方式和填充。

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

#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 控件,并添加多个子控件,这些子控件可以通过滚动条进行浏览。

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 属性来控制滚动方向(水平或垂直)。

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 事件处理程序,以处理滚动事件。

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 控件,并处理滚动事件。

#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 都代表一个子控件的插槽,可以通过链式调用设置对齐方式和填充等属性。

+ SScrollBox::Slot()
[
    SNew(STextBlock)
    .Text(FText::FromString("Item 1"))
]

使用 Orientation 属性设置滚动方向,默认为垂直方向(Orient_Vertical)。

SNew(SScrollBox)
.Orientation(Orient_Horizontal)

使用 OnUserScrolled 属性绑定滚动事件处理程序,当用户滚动时,会调用指定的处理函数。

.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 方法中使用声明式语法添加子控件。

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元素。
class SMyLeafWidget : public SLeafWidget
{
public:
    SLATE_BEGIN_ARGS(SMyLeafWidget) {}
    SLATE_END_ARGS()

    void Construct(const FArguments& InArgs)
    {
        // 无子控件,通常用于独立元素
    }
};
  1. SPanel
    SPanel 继承自 SWidget,用于管理和排列多个子控件。具体布局控件(如 SHorizontalBox, SVerticalBox)继承自 SPanel
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 控件:

#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 中:

#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 控件:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1703748.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

闲话 .NET(7):.NET Core 能淘汰 .NET FrameWork 吗?

前言 虽然说&#xff0c;目前 .NET FrameWork 上的大部分类都已经移植到 .NET Core 上&#xff0c;而且 .NET FrameWork 也已经停止了更新&#xff0c;未来必然是 .NET Core 的天下&#xff0c;但要说现在 .NET Core 就能淘汰 .NET FrameWork&#xff0c;我觉得为时尚早&#…

C++学习笔记(21)——继承

目录 1. 继承的概念及定义1.1 继承的概念1.2 继承定义1.2.1 定义格式1.2.2 继承关系和访问限定符1.2.3 继承基类成员访问方式的变化 继承的概念总结&#xff1a; 2. 基类和派生类对象赋值转换3.继承中的作用域4.派生类的默认成员函数知识点&#xff1a;派生类中6个默认成员函数…

利用java8 的 CompletableFuture 优化 Flink 程序,性能提升 50%

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

【吊打面试官系列】Java高并发篇 - ConcurrentHashMap 的并发度是什么?

大家好&#xff0c;我是锋哥。今天分享关于 【ConcurrentHashMap 的并发度是什么?】面试题&#xff0c;希望对大家有帮助&#xff1b; ConcurrentHashMap 的并发度是什么? ConcurrentHashMap 的并发度就是 segment 的大小&#xff0c;默认为 16&#xff0c; 这意味着最多同时…

.DFS.

DFS 全称为Depth First Search&#xff0c;中文称为深度优先搜索。 这是一种用于遍历或搜索树或图的算法&#xff0c;其思想是: 沿着每一条可能的路径一个节点一个节点地往下搜索&#xff0c; 直到路径的终点&#xff0c;然后再回溯&#xff0c;直到所有路径搜索完为止。 DFS俗…

ComfyUI简单介绍

&#x1f353;什么是ComfyUI ComfyUI是一个为Stable Diffusion专门设计的基于节点的图形用户界面&#xff0c;可以通过各种不同的节点快速搭建自己的绘图工作流程。 软件打开之后是长这个样子&#xff1a; 同时软件本身是github上的一个开源项目&#xff0c;开源地址为&#…

I.MX6ULL Linux C语言开发环境搭建(点灯实验)

系列文章目录 I.MX6ULL Linux C语言开发 I.MX6ULL Linux C语言开发 系列文章目录一、前言二、硬件原理分析三、构建步骤一、 C语言运行环境构建二、软件编写三、链接脚本 四、实验程序编写五、编译下载验证 一、前言 汇编语言编写 LED 灯实验&#xff0c;但是实际开发过程中汇…

Python实现国密GmSSL

Python实现国密GmSSL 前言开始首先安装生成公钥与私钥从用户证书中读取公钥读取公钥生成签名验证签名加密解密 遇到的大坑参考文献 前言 首先我是找得到的gmssl库&#xff0c;经过实操&#xff0c;发现公钥与密钥不能通过pem文件得到&#xff0c;就是缺少导入pem文件的api。这…

maven的下载以及配置的详细教程(附网盘下载地址)

文章目录 下载配置IDEA内部使用配置 下载 1.百度网盘下载 链接: https://pan.baidu.com/s/1LD9wOMFalLL49XUscU4qnQ?pwd1234 提取码: 1234 2.解压即可 配置 1.打开安装文件下conf下的settings.xml文件&#xff0c;我的如下 2.修改配置信息&#xff08;目的是为了修改本地…

【技术分享】Maven常用配置

一、Maven简介 &#xff08;一&#xff09;为什么使用 Maven 由于 Java 的生态非常丰富&#xff0c;无论你想实现什么功能&#xff0c;都能找到对应的工具类&#xff0c;这些工具类都是以 jar 包的形式出现的&#xff0c;例如 Spring&#xff0c;SpringMVC、MyBatis、数据库驱…

MQ本地消息事务表

纯技术方案水文特此记录 MQ本地消息事务表解决了什么问题&#xff1f; MQ本地事务表方案解决了本地事务与消息发送的原子性问题&#xff0c;即&#xff1a;事务发起方在本地事务执行成功后消息必须发出去&#xff0c;否则就丢弃消息。实现本地事务和消息发送的原子性&#xf…

系统安全扫描扫出了:可能存在 CSRF 攻击怎么办

公司的H5在软件安全测试中被检查出可能存在 CSRF 攻击&#xff0c;网上找了一堆解决方法&#xff0c;最后用这种方式解决了。 1、问题描述 CSRF 是 Cross Site Request Forgery的缩写(也缩写为也就是在用户会话下对某个 CGI 做一些 GET/POST 的事&#xff0c;RIVTSTCNNARGO一这…

香橙派AIpro初体验,详解如何安装Home Assistant Supervised

香橙派AIpro&#xff08;OrangePi AIpro&#xff09;开发版&#xff0c;定位是一块AI开发板&#xff0c;搭载的是华为昇腾310&#xff08;Ascend310&#xff09;处理器。 没想到&#xff0c;这几年的发展&#xff0c;AI开发板也逐渐铺开&#xff0c;记得之前看到华为发布昇腾3…

挑战你的数据结构技能:复习题来袭【3】

chap3 练习1 一. 单选题 1. (单选题)栈和队列具有相同的&#xff08;&#xff09; A. 抽象数据类型B. 逻辑结构C. 存储结构D. 运算 答案: B:逻辑结构 答案分析&#xff1a;逻辑结构都属于线性结构,只是它们对数据的运算不同。 2. (单选题)栈是() A. 顺序存储的线性结构B…

深入理解python列表与字典:数据结构的选择与性能差异

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、列表与字典&#xff1a;基础数据结构的对比 二、列表&#xff1a;逐个遍历的查找方式 …

SARscape5.7已经支持3米陆探一号(LT-1)数据处理

SARsacpe5.6.2.1版本已经开始支持LT-1的数据处理&#xff0c;由于当时只获取了12米的条带模式2&#xff08;STRIP2&#xff09;例子数据&#xff0c;对3米条带模式1&#xff08;STRIP1&#xff09;数据的InSAR处理轨道误差挺大&#xff0c;可能会造成干涉图异常。 SARsacpe5.7最…

Android Display Graphics #1 整体框架介绍一

软件基础 Android的framework层提供了一系列的图像渲染API&#xff0c;可绘制2D和3D。简单理解就是上层开发APP的小伙伴提供了接口&#xff0c;开发者可以直接显示对应的自己内容。但如果掌握了Display底层逻辑再写上层app&#xff0c;会有掌控力&#xff0c;出问题可以根据lo…

vs code怎么补全路径,怎么快捷输入文件路径

安装插件&#xff1a; 链接&#xff1a;https://marketplace.visualstudio.com/items?itemNamejakob101.RelativePath 使用 按住 Ctrl Shift H&#xff0c;弹出窗口&#xff0c;输入文件补全&#xff0c;回车就可以了 排除文件 如果你的项目下文件太多&#xff0c;它会…

2000-2017年各省经济政策不确定性指数

2000-2017年各省经济政策不确定性指数 1、时间&#xff1a;2000-2017年 2、来源&#xff1a;国际能源转型学会 3、范围&#xff1a;31省 4、构建说明&#xff1a; 按照Baker等&#xff08;2016&#xff09;的方法&#xff0c;在中国省级范围内构建了经济政策不确定性&…

如果任务过多,队列积压怎么处理?

如果任务过多,队列积压怎么处理? 1、内存队列满了应该怎么办2、问题要治本——发短信导致吞吐量降低的问题不能忽略!!3、多路复用IO模型的核心组件简介1、内存队列满了应该怎么办 如图: 大家可以看到,虽然现在发短信和广告投递,彼此之间的执行效率不受彼此影响,但是请…