Slate的应用(笔记三)

Slate的应用

  • 在插件目录下分别在public文件夹和private文件夹下创建HelloSlate.h、CustomBox.h和HelloSlate.cpp、CustomBox.cpp文件。然后再Generate一下。
    在这里插入图片描述
    在这里插入图片描述
  • 分别在.h和.cpp文件里添加如下代码
    HelloSlate.h
 #pragma once
#include "SCompoundWidget.h"
#include "DeclarativeSyntaxSupport.h"
#include "CustomBox.h"
class SHelloSlate :public SCompoundWidget
{

public:

	SLATE_BEGIN_ARGS(SHelloSlate)
	{}
	SLATE_END_ARGS()
	//构造
    void Construct(const FArguments& InArgs);
	//鼠标点击
	FReply OnButtonClicked();
	//输入结束
	void OnTextBoxCommitted(const FText& InputText, ETextCommit::Type CommitType);

public:
	//单选框点击
	void OnValueChanged(int32 Num);

	FString InputText;
	int32 Index;
protected:
	//单选框数组
	TArray<	TSharedPtr<SCustomBox> > CustomBoxArray;
};

我们可以使用SLATE_BEGIN_ARGS和SLATE_END_ARGS来声明和构建一个Widget。
官方实例e.g.

SLATE_BEGIN_ARGS( SMyWidget )
, _PreferredWidth( 150.0f )
, _ForegroundColor( FLinearColor::White )
     {}
SLATE_ATTRIBUTE(float, PreferredWidth)
SLATE_ATTRIBUTE(FSlateColor, ForegroundColor)
SLATE_END_ARGS()

HelloSlate.cpp

#include "HelloSlate.h"
#include "SOverlay.h"
#include "SBoxPanel.h"
#include "STextBlock.h"
#include "SEditableTextBox.h"
#include "SButton.h"
#include "MessageDialog.h"

#define LOCTEXT_NAMESPACE "HelloSlate"
void SHelloSlate::Construct(const FArguments & InArgs)
{
	CustomBoxArray.SetNum(2);//设置单选框数量
	ChildSlot
	[
		SNew(SOverlay)
		+ SOverlay::Slot()
		[
			SNew(SVerticalBox)
			+SVerticalBox::Slot()
			.AutoHeight()
			.VAlign(VAlign_Fill)
			.HAlign(HAlign_Fill)
			[
				SNew(SHorizontalBox)
				+SHorizontalBox::Slot()
				.AutoWidth()
				.HAlign(HAlign_Center)
				.VAlign(VAlign_Center)
				[
					SNew(STextBlock).Text(LOCTEXT("mingzi","Name:"))
				]
				+SHorizontalBox::Slot()
				.FillWidth(1.0f)
				.HAlign(HAlign_Fill)
				.VAlign(VAlign_Fill)
				[
					SNew(SEditableTextBox)
					.OnTextCommitted(this,&SHelloSlate::OnTextBoxCommitted)
				]
			]
			+ SVerticalBox::Slot()
			.AutoHeight()
			.VAlign(VAlign_Fill)
			.HAlign(HAlign_Fill)
			[
				SNew(SHorizontalBox)
				+ SHorizontalBox::Slot()
				.FillWidth(1.0f)
				.HAlign(HAlign_Left)
				.VAlign(VAlign_Center)
				[
					SNew(STextBlock).Text(LOCTEXT("xingbie", "Gender:"))
				]
				+ SHorizontalBox::Slot()
					.FillWidth(1.0f)
					.HAlign(HAlign_Left)
					.VAlign(VAlign_Center)
				[
				//以下是自定义控件(将单选框和其对应文本绑定)
					SAssignNew(CustomBoxArray[0],SCustomBox)
					.Gender("Female")
					.IndexNum(0)
					.CurrentState(ECheckBoxState::Checked)
					.OnChecked(this, &SHelloSlate::OnValueChanged)
				]
				+ SHorizontalBox::Slot()
					.FillWidth(1.0f)
					.HAlign(HAlign_Left)
					.VAlign(VAlign_Center)
				[
					SAssignNew(CustomBoxArray[1], SCustomBox)
					.Gender("Male")
					.IndexNum(1)
					.CurrentState(ECheckBoxState::Unchecked)
					.OnChecked(this,&SHelloSlate::OnValueChanged)
				]
			] 
			+ SVerticalBox::Slot()
			.FillHeight(1.0f)
			.HAlign(HAlign_Right)
			.VAlign(VAlign_Bottom)
			[
				SNew(SButton).OnClicked(this, &SHelloSlate::OnButtonClicked)
			]
		]
	
	];
}

以上为Widget的布局,大致如下(一般咱们都会先在UE4里把Widget搞出来,然后再根据Widget再来写slate):
举个小栗子:
~俗话说,有缘千里来相会(懒癌突然附体,别嫌图太长)

在这里插入图片描述


FReply SHelloSlate::OnButtonClicked()
{
	bool HaveChoose = false;
	int32 Index;
	if (InputText != "")
	{
		for (int32 i = 0; i < CustomBoxArray.Num(); i++)
		{
			if (CustomBoxArray[i]->CurrentState == ECheckBoxState::Checked)
			{
				HaveChoose = true;
				Index = i;
			}
		}
		if (HaveChoose)
		{
			FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("name : " + InputText + "\n" + "Gender : " + CustomBoxArray[Index]->Gender));
		}
		else
		{
			FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Gender is not null"));
		}
	}
	else 
		{
			FMessageDialog::Open(EAppMsgType::Ok, FText::FromString("Name is not null "));
		}
	return FReply::Handled();
}
void SHelloSlate::OnTextBoxCommitted(const FText & InputTex, ETextCommit::Type CommitType)
{
	if (CommitType == ETextCommit::OnUserMovedFocus|| ETextCommit::OnEnter)
	{
		InputText = InputTex.ToString();
	}
}

void SHelloSlate::OnValueChanged(int32 Num)
{
//实现单选操作
	if (CustomBoxArray[Num]->CurrentState == ECheckBoxState::Unchecked)
	{
		for (int32 i = 0; i < CustomBoxArray.Num(); i++)
		{
			if (i != Num)
			{
				CustomBoxArray[i]->CheckBox->SetIsChecked(ECheckBoxState::Unchecked);
				CustomBoxArray[i]->CurrentState = ECheckBoxState::Unchecked;
			}
		}
	}
}

#undef  LOCTEXT_NAMESPACE

CustomBox.h

#pragma once
#include "CoreMinimal.h"
#include "SCompoundWidget.h"
#include "SCheckBox.h"
//声明委托
DECLARE_DELEGATE_OneParam(FOnChecked,int32)

class SCustomBox :public SCompoundWidget
{

public:
	SLATE_BEGIN_ARGS(SCustomBox)
	{
		_Gender = "";
	}

	//传递代理
	SLATE_EVENT(FOnChecked, OnChecked)
	//传递参数
	SLATE_ARGUMENT(ECheckBoxState, CurrentState)

	SLATE_ARGUMENT(FString, Gender)

	SLATE_ARGUMENT(int32, IndexNum)

	SLATE_END_ARGS()

    void Construct(const FArguments& InArgs);

	FOnChecked OnChecked;

	FString Gender;

	ECheckBoxState CurrentState;

	void ChangeBoxState(ECheckBoxState State);

	TSharedPtr<SCheckBox> CheckBox;

	int32 IndexNum;
};

CustomBox.cpp

#include "CustomBox.h"
#include "STextBlock.h"
void SCustomBox::Construct(const FArguments & InArgs)
{
	OnChecked = InArgs._OnChecked;
	Gender = InArgs._Gender;
	CurrentState = InArgs._CurrentState;
	IndexNum = InArgs._IndexNum;

	ChildSlot
	[
		SAssignNew(CheckBox,SCheckBox)
		.IsChecked(CurrentState)
		.OnCheckStateChanged(this,&SCustomBox::ChangeBoxState)
		[
			SNew(STextBlock)
			.Text(FText::FromString(Gender))
		]
	];
}


void SCustomBox::ChangeBoxState(ECheckBoxState NewState)
{
	//执行代理
	OnChecked.ExecuteIfBound(IndexNum);
	CurrentState = NewState;
}

最后效果如下所示:
在这里插入图片描述

发布了3 篇原创文章 · 获赞 0 · 访问量 47

猜你喜欢

转载自blog.csdn.net/m0_45029082/article/details/104678823