这里将会自定义一个按钮
首先在 Public 下创建一个 SlateWidget 类
d:ue4 projectue26.2courseprojectslaicourseSourceSlAiCoursePublicUIWidgetSSlAiMenuWidget.h
#include "CoreMinimal.h"
#include "Data/SlAiTypes.h"
#include "Widgets/SCompoundWidget.h"
class SBox;
class STextBlock;
class SVerticalBox;
class SLAICOURSE_API SSlAiMenuWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SSlAiMenuWidget)
{}
SLATE_END_ARGS()
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
private:
//绑定到各个MenuItem的方法
void MenuItemOnClicked(EMenuItem::Type ItemType);
private:
//保存根节点,用来动态的修改SBox的大小
TSharedPtr<SBox> RootSizeBox;
//获取MenuStyle
const struct FSlAiMenuStyle* MenuStyle;
//保存标题
TSharedPtr<STextBlock> TitleText;
//用来保存垂直列表,所有的菜单按钮组件都会放置到这ContentBox中
TSharedPtr<SVerticalBox> ContentBox;
};
d:ue4 projectue26.2courseprojectslaicourseSourceSlAiCoursePrivateUIWidgetSSlAiMenuWidget.cpp
#include "UI/Widget/SSlAiMenuWidget.h"
#include "SlateOptMacros.h"
#include "UI/Style/SlAiStyle.h"
#include "UI/Style/SlAiMenuWidgetStyle.h"
#include "Widgets/Layout/SBox.h" //一版会把SlateWidget的根组件设成SBox
#include "Widgets/Images/SImage.h"
#include "Widgets/Text/STextBlock.h"
#include "Internationalization/Internationalization.h" //一个关于本地化的头文件
#include "UI/Widget/SSlAiMenuItemWidget.h"
#include "Widgets/SBoxPanel.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SSlAiMenuWidget::Construct(const FArguments& InArgs)
{
//获取MenuStyle
MenuStyle = &SlAiStyle::Get().GetWidgetStyle<FSlAiMenuStyle>("BPSlAiMenuStyle");
/**
*切换语言
*/
FInternationalization::Get().SetCurrentCulture(TEXT("en"));
//FInternationalization::Get().SetCurrentCulture(TEXT("ch"));
ChildSlot
[
/**
*没有Slot,没有Slot要么不能插入子组件,要么只能插入一个子组件,SizeBox 只能插入一个子组件
*/
SAssignNew(RootSizeBox, SBox)
[
SNew(SOverlay)
+SOverlay::Slot() //主菜单背景
.HAlign(HAlign_Fill)
.VAlign(VAlign_Fill)
.Padding(FMargin(0.f, 50.f, 0.f, 0.f)) //FMargin 间隔(左 上 右 下)
[
SNew(SImage)
.Image(&MenuStyle->MenuBackgroundBrush)
]
+SOverlay::Slot() //菜单左侧图片
.HAlign(HAlign_Left)
.VAlign(VAlign_Center)
.Padding(FMargin(0.f, 25.f, 0.f, 0.f))
[
SNew(SImage).Image(&MenuStyle->LeftIconBrush)
]
+SOverlay::Slot() //菜单右侧图片
.HAlign(HAlign_Right)
.VAlign(VAlign_Center)
.Padding(FMargin(0.f, 25.f, 0.f, 0.f))
[
SNew(SImage).Image(&MenuStyle->RightIconBrush)
]
+SOverlay::Slot() //菜单标题图片
.HAlign(HAlign_Center)
.VAlign(VAlign_Top)
[
SNew(SBox)
.WidthOverride(400.f)
.HeightOverride(100.f)
[
SNew(SBorder)
.BorderImage(&MenuStyle->TitleBorderBrush)
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SAssignNew(TitleText, STextBlock)
.Font(SlAiStyle::Get().GetFontStyle("MenuItemFort"))
.Text(NSLOCTEXT("SlAiMenu", "Menu", "Menu"))
//.Font(MenuStyle->Font_60)
]
]
]
+SOverlay::Slot() //菜单按钮组件
.HAlign(HAlign_Center)
.VAlign(VAlign_Top)
.Padding(FMargin(0.f, 130.f, 0.f, 0.f))
[
//菜单组件创建到这里
SAssignNew(ContentBox, SVerticalBox)
]
]
];
/**
* RootSizeBox在生成的时候没有设置他的宽和高,这里设置下
*/
RootSizeBox->SetWidthOverride(600.f);
RootSizeBox->SetHeightOverride(510.f);
/*******************************************************************
*ContentBox->AddSlot() 等同于在 ChildSlot 下的 SAssignNew(ContentBox, SVerticalBox) 层级下添加:
*
SAssignNew(ContentBox, SVerticalBox)
+SVerticalBox::Slot()
[
SNew(SSlAiMenuItemWidget)
.ItemText(NSLOCTEXT("SlAimenu", "StartGame", "StartGame"))
.ItemType(EMenuItem::StartGame)
.OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)
]
*
****************************************************************/
ContentBox->AddSlot()
[
SNew(SSlAiMenuItemWidget)
.ItemText(NSLOCTEXT("SlAimenu", "StartGame", "StartGame"))
.ItemType(EMenuItem::StartGame)
.OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)
];
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SSlAiMenuWidget::MenuItemOnClicked(EMenuItem::Type ItemType)
{
}
D:UE4 ProjectUE26.2CourseProjectSlAiCourseSourceSlAiCoursePublicUIStyleSlAiMenuWidgetStyle.h
#include "CoreMinimal.h"
#include "Styling/SlateWidgetStyle.h"
#include "Styling/SlateWidgetStyleContainerBase.h"
#include "Styling/SlateBrush.h"
#include "Fonts/SlateFontInfo.h"
#include "SlAiMenuWidgetStyle.generated.h"
USTRUCT()
struct SLAICOURSE_API FSlAiMenuStyle : public FSlateWidgetStyle //构造体
{
GENERATED_USTRUCT_BODY()
FSlAiMenuStyle();
virtual ~FSlAiMenuStyle();
// FSlateWidgetStyle
virtual void GetResources(TArray<const FSlateBrush*>& OutBrushes) const override;
static const FName TypeName;
virtual const FName GetTypeName() const override { return TypeName; };
static const FSlAiMenuStyle& GetDefault();
/*定义笔刷
* 主背景图片*/
UPROPERTY(EditAnywhere, Category = MenuHUD)
FSlateBrush MenuHUDBackgroundBrush;
/*定义笔刷
* 主背景图片*/
UPROPERTY(EditAnywhere, Category = Menu)
FSlateBrush MenuBackgroundBrush;
/*定义笔刷
* Menu左图标的Brush*/
UPROPERTY(EditAnywhere, Category = Menu)
FSlateBrush LeftIconBrush;
/*定义笔刷
* Menu右图标的Brush*/
UPROPERTY(EditAnywhere, Category = Menu)
FSlateBrush RightIconBrush;
/*定义笔刷
* Menu标题Border的Brush*/
UPROPERTY(EditAnywhere, Category = Menu)
FSlateBrush TitleBorderBrush;
/*定义笔刷
* MenuItem的Brush*/
UPROPERTY(EditAnywhere, Category = MenuItem)
FSlateBrush MenuItemBrush;
/**
* 30号字体 */
UPROPERTY(EditAnywhere, Category = Common)
FSlateFontInfo Font_30;
/**
* 40号字体 */
UPROPERTY(EditAnywhere, Category = Common)
FSlateFontInfo Font_40;
/**
* 60号字体 */
UPROPERTY(EditAnywhere, Category = Common)
FSlateFontInfo Font_60;
};
UCLASS(hidecategories=Object, MinimalAPI)
class USlAiMenuWidgetStyle : public USlateWidgetStyleContainerBase
{
GENERATED_BODY()
public:
/** The actual data describing the widget appearance. */
UPROPERTY(Category=Appearance, EditAnywhere, meta=(ShowOnlyInnerProperties))
FSlAiMenuStyle WidgetStyle;
virtual const struct FSlateWidgetStyle* const GetStyle() const override
{
return static_cast< const struct FSlateWidgetStyle* >( &WidgetStyle );
}
};
D:UE4 ProjectUE26.2CourseProjectSlAiCourseSourceSlAiCoursePublicUIWidgetSSlAiMenuItemWidget.h
#include "CoreMinimal.h"
#include "Widgets/SCompoundWidget.h"
#include "Data/SlAiTypes.h"
/**
* 定义委托
* 按钮点击事件需要先定义一个委托,_OneParam 一个参数的委托,(委托的名字,传入的变量)
*/
DECLARE_DELEGATE_OneParam(FItemClicked, const EMenuItem::Type)
/**
*
*/
class SLAICOURSE_API SSlAiMenuItemWidget : public SCompoundWidget
{
public:
SLATE_BEGIN_ARGS(SSlAiMenuItemWidget)
{}
SLATE_EVENT(FItemClicked, OnClicked) //运行这个控件,委托FItemClicked,触发 OnClicked, OnClicked绑定MenuItemOnClicked函数指针
SLATE_ATTRIBUTE(FText, ItemText) //变量类型,变量名
SLATE_ATTRIBUTE(EMenuItem::Type, ItemType)
SLATE_END_ARGS()
/** Constructs this widget with InArgs */
void Construct(const FArguments& InArgs);
/**
* 重写组件的OnMouseButtonDown方法*/
virtual FReply OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
/**
* 重写按钮起来的方法*/
virtual FReply OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent) override;
/**
* 重写鼠标离开的方法 */
virtual void OnMouseLeave(const FPointerEvent& MouseEvent) override;
private:
/*
获取颜色*/
FSlateColor GetTineColor() const;
private:
//按下事件委托
FItemClicked OnClicked; /**
* SSlAiMenuItemWidget.cpp 中的 FArguments& InArgs 可以获取到该类中的所有东西,
* 如 OnClicked = InArgs._OnClicked;
* 他对应的是 SLATE_EVENT 或 SLATE_ATTRIBUTE 中的那些名字
*/
//保存按钮类型
EMenuItem::Type ItemType;
//获取MenuStyle
const struct FSlAiMenuStyle* MenuStyle;
//按钮是否已经按下
bool IsMouseButtonDown;
};
D:UE4 ProjectUE26.2CourseProjectSlAiCourseSourceSlAiCoursePrivateUIWidgetSSlAiMenuItemWidget.cpp
#include "UI/Widget/SSlAiMenuItemWidget.h"
#include "SlateOptMacros.h"
#include "UI/Style/SlAiStyle.h"
#include "UI/Style/SlAiMenuWidgetStyle.h"
#include "Widgets/Layout/SBox.h"
#include "Widgets/Images/SImage.h"
#include "Widgets/Text/STextBlock.h"
BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
void SSlAiMenuItemWidget::Construct(const FArguments& InArgs)
{
//获取MenuStyle
MenuStyle = &SlAiStyle::Get().GetWidgetStyle<FSlAiMenuStyle>("BPSlAiMenuStyle");
/**
*SSlAiMenuWidget.cpp 新建控件的时候,通过AddSlot中传入的属性,在此处赋值到自己定义的变量里边
*/
OnClicked = InArgs._OnClicked;
ItemType = InArgs._ItemType.Get();
ChildSlot
[
SNew(SBox)
.WidthOverride(500.f)
.HeightOverride(100.f)
[
SNew(SOverlay)
+SOverlay::Slot() //按钮
.VAlign(VAlign_Fill)
.HAlign(HAlign_Fill)
[
SNew(SImage)
.Image(&MenuStyle->MenuItemBrush)
/*颜色和透明值绑定一个方法
* 绑定之后每一帧都会调用一次这个方法
* 如果发现这个方法值改变了,那么就会改变自己颜色
*/
.ColorAndOpacity(this, &SSlAiMenuItemWidget::GetTineColor)
]
+SOverlay::Slot() //文字
.HAlign(HAlign_Center)
.VAlign(VAlign_Center)
[
SNew(STextBlock)
.Text(InArgs._ItemText) //可直接通过InArgs获取ItemText
.Font(MenuStyle->Font_60)
]
]
];
//初始化
IsMouseButtonDown = false;
}
END_SLATE_FUNCTION_BUILD_OPTIMIZATION
//鼠标按下触发
FReply SSlAiMenuItemWidget::OnMouseButtonDown(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
IsMouseButtonDown = true;
return FReply::Handled();
}
//鼠标抬起触发
FReply SSlAiMenuItemWidget::OnMouseButtonUp(const FGeometry& MyGeometry, const FPointerEvent& MouseEvent)
{
/*如果按下了并且OnClicked委托绑定有方法那就执行
*/
if (IsMouseButtonDown)
{
IsMouseButtonDown = false;
/*运行委托,.Execute不会判断有没有绑定,.ExecuteIfBound是有绑定
*/
OnClicked.ExecuteIfBound(ItemType);
}
return FReply::Handled();
}
//鼠标移开触发
void SSlAiMenuItemWidget::OnMouseLeave(const FPointerEvent& MouseEvent)
{
/*鼠标按着滑到别的地方,要将鼠标事件false掉
*/
IsMouseButtonDown = false;
}
/*当这个方法传回来的值 FLinearColor 有改变的时候,调用的 ColorAndOpacity 就会有变化
*/
FSlateColor SSlAiMenuItemWidget::GetTineColor() const
{
/*根据鼠标是否有按下来触发
*/
if (IsMouseButtonDown)
{
/*函数类型是 FSlateColor,返回值是FLinearColor,这样是没有问题的
* FSlateColor 重写了一些构造函数,如果传给他一个 FLinearColor 会转换成 FSlateColor
* 这是C++的知识
*/
return FLinearColor(1.f, 0.f, 0.1f, 0.5f);
}
else
{
return FLinearColor(1.f, 1.f, 1.f, 1.f);
}
}
原文链接: https://www.cnblogs.com/CooCoChoco/p/15075507.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/212818
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!